Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / android_crazy_linker / src / src / crazy_linker_shared_library.cpp
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 #include "crazy_linker_shared_library.h"
6
7 #include <dlfcn.h>
8 #include <stdlib.h>
9 #include <sys/mman.h>
10 #include <elf.h>
11
12 #include "crazy_linker_ashmem.h"
13 #include "crazy_linker_debug.h"
14 #include "crazy_linker_elf_loader.h"
15 #include "crazy_linker_elf_relocations.h"
16 #include "crazy_linker_library_list.h"
17 #include "crazy_linker_library_view.h"
18 #include "crazy_linker_globals.h"
19 #include "crazy_linker_memory_mapping.h"
20 #include "crazy_linker_thread.h"
21 #include "crazy_linker_util.h"
22 #include "crazy_linker_wrappers.h"
23 #include "linker_phdr.h"
24
25 #ifndef DF_SYMBOLIC
26 #define DF_SYMBOLIC 2
27 #endif
28
29 #ifndef DF_TEXTREL
30 #define DF_TEXTREL 4
31 #endif
32
33 #ifndef DT_INIT_ARRAY
34 #define DT_INIT_ARRAY 25
35 #endif
36
37 #ifndef DT_INIT_ARRAYSZ
38 #define DT_INIT_ARRAYSZ 27
39 #endif
40
41 #ifndef DT_FINI_ARRAY
42 #define DT_FINI_ARRAY 26
43 #endif
44
45 #ifndef DT_FINI_ARRAYSZ
46 #define DT_FINI_ARRAYSZ 28
47 #endif
48
49 #ifndef DT_FLAGS
50 #define DT_FLAGS 30
51 #endif
52
53 #ifndef DT_PREINIT_ARRAY
54 #define DT_PREINIT_ARRAY 32
55 #endif
56
57 #ifndef DT_PREINIT_ARRAYSZ
58 #define DT_PREINIT_ARRAYSZ 33
59 #endif
60
61 #ifndef DT_LOOS
62 #define DT_LOOS 0x6000000d
63 #endif
64
65 // Extension dynamic tags for packed relocations.
66 #if defined(__arm__) || defined(__aarch64__)
67
68 #define DT_ANDROID_REL_OFFSET (DT_LOOS)
69 #define DT_ANDROID_REL_SIZE (DT_LOOS + 1)
70
71 #endif  // __arm__ || __aarch64__
72
73 namespace crazy {
74
75 namespace {
76
77 typedef SharedLibrary::linker_function_t linker_function_t;
78 typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved);
79 typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved);
80
81 // Call a constructor or destructor function pointer. Ignore
82 // NULL and -1 values intentionally. They correspond to markers
83 // in the tables, or deleted values.
84 // |func_type| corresponds to the type of the function, and is only
85 // used for debugging (examples are "DT_INIT", "DT_INIT_ARRAY", etc...).
86 void CallFunction(linker_function_t func, const char* func_type) {
87   uintptr_t func_address = reinterpret_cast<uintptr_t>(func);
88
89   LOG("%s: %p %s\n", __FUNCTION__, func, func_type);
90   if (func_address != 0 && func_address != uintptr_t(-1))
91     func();
92 }
93
94 // An instance of ElfRelocator::SymbolResolver that can be used
95 // to resolve symbols in a shared library being loaded by
96 // LibraryList::LoadLibrary.
97 class SharedLibraryResolver : public ElfRelocations::SymbolResolver {
98  public:
99   SharedLibraryResolver(SharedLibrary* lib,
100                         LibraryList* lib_list,
101                         Vector<LibraryView*>* dependencies)
102       : lib_(lib), dependencies_(dependencies) {}
103
104   virtual void* Lookup(const char* symbol_name) {
105     // TODO(digit): Add the ability to lookup inside the main executable.
106
107     // First, look inside the current library.
108     const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name);
109     if (entry)
110       return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value);
111
112     // Special case: redirect the dynamic linker symbols to our wrappers.
113     // This ensures that loaded libraries can call dlopen() / dlsym()
114     // and transparently use the crazy linker to perform their duty.
115     void* address = WrapLinkerSymbol(symbol_name);
116     if (address)
117       return address;
118
119     // Then look inside the dependencies.
120     for (size_t n = 0; n < dependencies_->GetCount(); ++n) {
121       LibraryView* wrap = (*dependencies_)[n];
122       // LOG("%s: Looking into dependency %p (%s)\n", __FUNCTION__, wrap,
123       // wrap->GetName());
124       if (wrap->IsSystem()) {
125         address = ::dlsym(wrap->GetSystem(), symbol_name);
126 #ifdef __arm__
127         // Android libm.so defines isnanf as weak. This means that its
128         // address cannot be found by dlsym(), which always returns NULL
129         // for weak symbols. However, libm.so contains the real isnanf
130         // as __isnanf. If we encounter isnanf and fail to resolve it in
131         // libm.so, retry with __isnanf.
132         //
133         // This occurs only in clang, which lacks __builtin_isnanf. The
134         // gcc compiler implements isnanf as a builtin, so the symbol
135         // isnanf never need be resolved in gcc builds.
136         //
137         // http://code.google.com/p/chromium/issues/detail?id=376828
138         if (!address &&
139             !strcmp(symbol_name, "isnanf") &&
140             !strcmp(wrap->GetName(), "libm.so"))
141           address = ::dlsym(wrap->GetSystem(), "__isnanf");
142 #endif
143         if (address)
144           return address;
145       }
146       if (wrap->IsCrazy()) {
147         SharedLibrary* dep = wrap->GetCrazy();
148         entry = dep->LookupSymbolEntry(symbol_name);
149         if (entry)
150           return reinterpret_cast<void*>(dep->load_bias() + entry->st_value);
151       }
152     }
153
154     // Nothing found here.
155     return NULL;
156   }
157
158  private:
159   SharedLibrary* lib_;
160   Vector<LibraryView*>* dependencies_;
161 };
162
163 #if defined(__arm__) || defined(__aarch64__)
164
165 // Helper class to provide a simple scoped buffer.  ScopedPtr is not
166 // usable here because it calls delete, not delete [].
167 class ScopedBuffer {
168  public:
169   explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { }
170   ~ScopedBuffer() { delete [] buffer_; }
171
172   uint8_t* Get() { return buffer_; }
173
174   uint8_t* Release() {
175     uint8_t* ptr = buffer_;
176     buffer_ = NULL;
177     return ptr;
178   }
179
180  private:
181   uint8_t* buffer_;
182 };
183
184 // Read an .android.rel.dyn packed relocations section.
185 // Returns an allocated buffer holding the data, or NULL on error.
186 uint8_t* ReadPackedRelocations(const char* full_path,
187                                off_t offset,
188                                size_t bytes,
189                                Error* error) {
190   FileDescriptor fd;
191   if (!fd.OpenReadOnly(full_path)) {
192     error->Format("Error opening file '%s'", full_path);
193     return NULL;
194   }
195   if (fd.SeekTo(offset) == -1) {
196     error->Format("Error seeking to %d in file '%s'", offset, full_path);
197     return NULL;
198   }
199
200   ScopedBuffer buffer(bytes);
201   const ssize_t bytes_read = fd.Read(buffer.Get(), bytes);
202   if (static_cast<size_t>(bytes_read) != bytes) {
203     error->Format("Error reading %d bytes from file '%s'", bytes, full_path);
204     return NULL;
205   }
206   fd.Close();
207
208   uint8_t* packed_data = buffer.Release();
209   return packed_data;
210 }
211
212 #endif  // __arm__ || __aarch64__
213
214 }  // namespace
215
216 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); }
217
218 SharedLibrary::~SharedLibrary() {
219   // Ensure the library is unmapped on destruction.
220   if (view_.load_address())
221     munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size());
222
223 #if defined(__arm__) || defined(__aarch64__)
224   delete [] packed_relocations_;
225 #endif
226 }
227
228 bool SharedLibrary::Load(const char* full_path,
229                          size_t load_address,
230                          size_t file_offset,
231                          bool no_map_exec_support_fallback_enabled,
232                          Error* error) {
233   // First, record the path.
234   LOG("%s: full path '%s'\n", __FUNCTION__, full_path);
235
236   size_t full_path_len = strlen(full_path);
237   if (full_path_len >= sizeof(full_path_)) {
238     error->Format("Path too long: %s", full_path);
239     return false;
240   }
241
242   strlcpy(full_path_, full_path, sizeof(full_path_));
243   base_name_ = GetBaseNamePtr(full_path_);
244
245   // Load the ELF binary in memory.
246   LOG("%s: Loading ELF segments for %s\n", __FUNCTION__, base_name_);
247
248   {
249     ElfLoader loader(no_map_exec_support_fallback_enabled);
250     if (!loader.LoadAt(full_path_, file_offset, load_address, error)) {
251       return false;
252     }
253
254     if (!view_.InitUnmapped(loader.load_start(),
255                             loader.loaded_phdr(),
256                             loader.phdr_count(),
257                             error)) {
258       return false;
259     }
260
261     if (!symbols_.Init(&view_)) {
262       *error = "Missing or malformed symbol table";
263       return false;
264     }
265   }
266
267   if (phdr_table_get_relro_info(view_.phdr(),
268                                 view_.phdr_count(),
269                                 view_.load_bias(),
270                                 &relro_start_,
271                                 &relro_size_) < 0) {
272     relro_start_ = 0;
273     relro_size_ = 0;
274   }
275
276 #ifdef __arm__
277   LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_);
278   (void)phdr_table_get_arm_exidx(
279       phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_);
280 #endif
281
282 #if defined(__arm__) || defined(__aarch64__)
283   off_t packed_relocations_offset = 0;
284   size_t packed_relocations_size = 0;
285 #endif
286
287   LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_);
288   ElfView::DynamicIterator dyn(&view_);
289   for (; dyn.HasNext(); dyn.GetNext()) {
290     ELF::Addr dyn_value = dyn.GetValue();
291     uintptr_t dyn_addr = dyn.GetAddress(load_bias());
292     switch (dyn.GetTag()) {
293       case DT_DEBUG:
294         if (view_.dynamic_flags() & PF_W) {
295           *dyn.GetValuePointer() =
296               reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress());
297         }
298         break;
299       case DT_INIT:
300         LOG("  DT_INIT addr=%p\n", dyn_addr);
301         init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
302         break;
303       case DT_FINI:
304         LOG("  DT_FINI addr=%p\n", dyn_addr);
305         fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
306         break;
307       case DT_INIT_ARRAY:
308         LOG("  DT_INIT_ARRAY addr=%p\n", dyn_addr);
309         init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
310         break;
311       case DT_INIT_ARRAYSZ:
312         init_array_count_ = dyn_value / sizeof(ELF::Addr);
313         LOG("  DT_INIT_ARRAYSZ value=%p count=%p\n",
314             dyn_value,
315             init_array_count_);
316         break;
317       case DT_FINI_ARRAY:
318         LOG("  DT_FINI_ARRAY addr=%p\n", dyn_addr);
319         fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
320         break;
321       case DT_FINI_ARRAYSZ:
322         fini_array_count_ = dyn_value / sizeof(ELF::Addr);
323         LOG("  DT_FINI_ARRAYSZ value=%p count=%p\n",
324             dyn_value,
325             fini_array_count_);
326         break;
327       case DT_PREINIT_ARRAY:
328         LOG("  DT_PREINIT_ARRAY addr=%p\n", dyn_addr);
329         preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
330         break;
331       case DT_PREINIT_ARRAYSZ:
332         preinit_array_count_ = dyn_value / sizeof(ELF::Addr);
333         LOG("  DT_PREINIT_ARRAYSZ value=%p count=%p\n",
334             dyn_value,
335             preinit_array_count_);
336         break;
337       case DT_SYMBOLIC:
338         LOG("  DT_SYMBOLIC\n");
339         has_DT_SYMBOLIC_ = true;
340         break;
341       case DT_FLAGS:
342         if (dyn_value & DF_SYMBOLIC)
343           has_DT_SYMBOLIC_ = true;
344         break;
345 #if defined(__arm__) || defined(__aarch64__)
346       case DT_ANDROID_REL_OFFSET:
347         packed_relocations_offset = dyn.GetOffset();
348         LOG("  DT_ANDROID_REL_OFFSET addr=%p\n", packed_relocations_offset);
349         break;
350       case DT_ANDROID_REL_SIZE:
351         packed_relocations_size = dyn.GetValue();
352         LOG("  DT_ANDROID_REL_SIZE=%d\n", packed_relocations_size);
353         break;
354 #endif
355 #if defined(__mips__)
356       case DT_MIPS_RLD_MAP:
357         *dyn.GetValuePointer() =
358             reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress());
359         break;
360 #endif
361       default:
362         ;
363     }
364   }
365
366 #if defined(__arm__) || defined(__aarch64__)
367   // If packed relocations are present in the target library, read the
368   // section data and save it in packed_relocations_.
369   if (packed_relocations_offset && packed_relocations_size) {
370     LOG("%s: Packed relocations found at offset %d, %d bytes\n",
371         __FUNCTION__,
372         packed_relocations_offset,
373         packed_relocations_size);
374
375     packed_relocations_ =
376         ReadPackedRelocations(full_path,
377                               packed_relocations_offset + file_offset,
378                               packed_relocations_size,
379                               error);
380     if (!packed_relocations_)
381       return false;
382
383     LOG("%s: Packed relocations stored at %p\n",
384         __FUNCTION__,
385         packed_relocations_);
386   }
387 #endif
388
389   LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_);
390   return true;
391 }
392
393 bool SharedLibrary::Relocate(LibraryList* lib_list,
394                              Vector<LibraryView*>* dependencies,
395                              Error* error) {
396   // Apply relocations.
397   LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_);
398
399   ElfRelocations relocations;
400
401   if (!relocations.Init(&view_, error))
402     return false;
403
404 #if defined(__arm__) || defined(__aarch64__)
405   relocations.RegisterPackedRelocations(packed_relocations_);
406 #endif
407
408   SharedLibraryResolver resolver(this, lib_list, dependencies);
409   if (!relocations.ApplyAll(&symbols_, &resolver, error))
410     return false;
411
412   LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_);
413   return true;
414 }
415
416 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) {
417   return symbols_.LookupByName(symbol_name);
418 }
419
420 void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) {
421   return symbols_.LookupAddressByName(symbol_name, view_.load_bias());
422 }
423
424 bool SharedLibrary::CreateSharedRelro(size_t load_address,
425                                       size_t* relro_start,
426                                       size_t* relro_size,
427                                       int* relro_fd,
428                                       Error* error) {
429   SharedRelro relro;
430
431   if (!relro.Allocate(relro_size_, base_name_, error))
432     return false;
433
434   if (load_address != 0 && load_address != this->load_address()) {
435     // Need to relocate the content of the ashmem region first to accomodate
436     // for the new load address.
437     if (!relro.CopyFromRelocated(
438              &view_, load_address, relro_start_, relro_size_, error))
439       return false;
440   } else {
441     // Simply copy, no relocations.
442     if (!relro.CopyFrom(relro_start_, relro_size_, error))
443       return false;
444   }
445
446   // Enforce read-only mode for the region's content.
447   if (!relro.ForceReadOnly(error))
448     return false;
449
450   // All good.
451   *relro_start = relro.start();
452   *relro_size = relro.size();
453   *relro_fd = relro.DetachFd();
454   return true;
455 }
456
457 bool SharedLibrary::UseSharedRelro(size_t relro_start,
458                                    size_t relro_size,
459                                    int relro_fd,
460                                    Error* error) {
461   LOG("%s: relro_start=%p relro_size=%p relro_fd=%d\n",
462       __FUNCTION__,
463       (void*)relro_start,
464       (void*)relro_size,
465       relro_fd);
466
467   if (relro_fd < 0 || relro_size == 0) {
468     // Nothing to do here.
469     return true;
470   }
471
472   // Sanity check: A shared RELRO is not already used.
473   if (relro_used_) {
474     *error = "Library already using shared RELRO section";
475     return false;
476   }
477
478   // Sanity check: RELRO addresses must match.
479   if (relro_start_ != relro_start || relro_size_ != relro_size) {
480     error->Format("RELRO mismatch addr=%p size=%p (wanted addr=%p size=%p)",
481                   relro_start_,
482                   relro_size_,
483                   relro_start,
484                   relro_size);
485     return false;
486   }
487
488   // Everything's good, swap pages in this process's address space.
489   SharedRelro relro;
490   if (!relro.InitFrom(relro_start, relro_size, relro_fd, error))
491     return false;
492
493   relro_used_ = true;
494   return true;
495 }
496
497 void SharedLibrary::CallConstructors() {
498   CallFunction(init_func_, "DT_INIT");
499   for (size_t n = 0; n < init_array_count_; ++n)
500     CallFunction(init_array_[n], "DT_INIT_ARRAY");
501 }
502
503 void SharedLibrary::CallDestructors() {
504   for (size_t n = fini_array_count_; n > 0; --n) {
505     CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY");
506   }
507   CallFunction(fini_func_, "DT_FINI");
508 }
509
510 bool SharedLibrary::SetJavaVM(void* java_vm,
511                               int minimum_jni_version,
512                               Error* error) {
513   if (java_vm == NULL)
514     return true;
515
516   // Lookup for JNI_OnLoad, exit if it doesn't exist.
517   JNI_OnLoadFunctionPtr jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>(
518       FindAddressForSymbol("JNI_OnLoad"));
519   if (!jni_onload)
520     return true;
521
522   int jni_version = (*jni_onload)(java_vm, NULL);
523   if (jni_version < minimum_jni_version) {
524     error->Format("JNI_OnLoad() in %s returned %d, expected at least %d",
525                   full_path_,
526                   jni_version,
527                   minimum_jni_version);
528     return false;
529   }
530
531   // Save the JavaVM handle for unload time.
532   java_vm_ = java_vm;
533   return true;
534 }
535
536 void SharedLibrary::CallJniOnUnload() {
537   if (!java_vm_)
538     return;
539
540   JNI_OnUnloadFunctionPtr jni_on_unload =
541       reinterpret_cast<JNI_OnUnloadFunctionPtr>(
542           this->FindAddressForSymbol("JNI_OnUnload"));
543
544   if (jni_on_unload)
545     (*jni_on_unload)(java_vm_, NULL);
546 }
547
548 bool SharedLibrary::DependencyIterator::GetNext() {
549   dep_name_ = NULL;
550   for (; iter_.HasNext(); iter_.GetNext()) {
551     if (iter_.GetTag() == DT_NEEDED) {
552       dep_name_ = symbols_->GetStringById(iter_.GetValue());
553       iter_.GetNext();
554       return true;
555     }
556   }
557   return false;
558 }
559
560 }  // namespace crazy