crazy_linker_shared_library.cpp revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_shared_library.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <dlfcn.h>
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdlib.h>
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/mman.h>
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <elf.h>
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_ashmem.h"
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_debug.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_loader.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_relocations.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_library_list.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_library_view.h"
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_globals.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_memory_mapping.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_thread.h"
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_util.h"
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_wrappers.h"
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "linker_phdr.h"
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DF_SYMBOLIC
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DF_SYMBOLIC 2
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DF_TEXTREL
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DF_TEXTREL 4
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_INIT_ARRAY
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_INIT_ARRAY 25
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_INIT_ARRAYSZ
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_INIT_ARRAYSZ 27
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_FINI_ARRAY
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_FINI_ARRAY 26
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_FINI_ARRAYSZ
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_FINI_ARRAYSZ 28
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_FLAGS
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_FLAGS 30
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_PREINIT_ARRAY
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_PREINIT_ARRAY 32
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_PREINIT_ARRAYSZ
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_PREINIT_ARRAYSZ 33
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef DT_LOOS
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define DT_LOOS 0x6000000d
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Extension dynamic tags for packed relocations.
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifdef __arm__
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define DT_ANDROID_REL_OFFSET (DT_LOOS)
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define DT_ANDROID_REL_SIZE (DT_LOOS + 1)
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif  // __arm__
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy {
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef SharedLibrary::linker_function_t linker_function_t;
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved);
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved);
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Call a constructor or destructor function pointer. Ignore
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NULL and -1 values intentionally. They correspond to markers
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// in the tables, or deleted values.
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |func_type| corresponds to the type of the function, and is only
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// used for debugging (examples are "DT_INIT", "DT_INIT_ARRAY", etc...).
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void CallFunction(linker_function_t func, const char* func_type) {
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uintptr_t func_address = reinterpret_cast<uintptr_t>(func);
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: %p %s\n", __FUNCTION__, func, func_type);
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (func_address != 0 && func_address != uintptr_t(-1))
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    func();
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// An instance of ElfRelocator::SymbolResolver that can be used
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to resolve symbols in a shared library being loaded by
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// LibraryList::LoadLibrary.
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class SharedLibraryResolver : public ElfRelocations::SymbolResolver {
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedLibraryResolver(SharedLibrary* lib,
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        LibraryList* lib_list,
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        Vector<LibraryView*>* dependencies)
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : lib_(lib), dependencies_(dependencies) {}
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void* Lookup(const char* symbol_name) {
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // TODO(digit): Add the ability to lookup inside the main executable.
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // First, look inside the current library.
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name);
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (entry)
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value);
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Special case: redirect the dynamic linker symbols to our wrappers.
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // This ensures that loaded libraries can call dlopen() / dlsym()
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // and transparently use the crazy linker to perform their duty.
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    void* address = WrapLinkerSymbol(symbol_name);
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (address)
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return address;
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Then look inside the dependencies.
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (size_t n = 0; n < dependencies_->GetCount(); ++n) {
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LibraryView* wrap = (*dependencies_)[n];
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // LOG("%s: Looking into dependency %p (%s)\n", __FUNCTION__, wrap,
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // wrap->GetName());
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (wrap->IsSystem()) {
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        address = ::dlsym(wrap->GetSystem(), symbol_name);
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // Android libm.so defines isnanf as weak. This means that its
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // address cannot be found by dlsym(), which always returns NULL
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // for weak symbols. However, libm.so contains the real isnanf
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // as __isnanf. If we encounter isnanf and fail to resolve it in
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // libm.so, retry with __isnanf.
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        //
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // This occurs only in clang, which lacks __builtin_isnanf. The
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // gcc compiler implements isnanf as a builtin, so the symbol
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // isnanf never need be resolved in gcc builds.
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        //
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // http://code.google.com/p/chromium/issues/detail?id=376828
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (!address &&
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            !strcmp(symbol_name, "isnanf") &&
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            !strcmp(wrap->GetName(), "libm.so"))
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          address = ::dlsym(wrap->GetSystem(), "__isnanf");
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (address)
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          return address;
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (wrap->IsCrazy()) {
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        SharedLibrary* dep = wrap->GetCrazy();
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        entry = dep->LookupSymbolEntry(symbol_name);
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (entry)
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          return reinterpret_cast<void*>(dep->load_bias() + entry->st_value);
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Nothing found here.
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return NULL;
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedLibrary* lib_;
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Vector<LibraryView*>* dependencies_;
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifdef __arm__
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Helper class to provide a simple scoped buffer.  ScopedPtr is not
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// usable here because it calls delete, not delete [].
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass ScopedBuffer {
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { }
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ~ScopedBuffer() { delete [] buffer_; }
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint8_t* Get() { return buffer_; }
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint8_t* Release() {
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint8_t* ptr = buffer_;
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    buffer_ = NULL;
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ptr;
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint8_t* buffer_;
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Read an .android.rel.dyn ARM packed relocations section.
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Returns an allocated buffer holding the data, or NULL on error.
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdochuint8_t* ReadArmPackedRelocs(const char* full_path,
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             off_t offset,
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             size_t bytes,
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             Error* error) {
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FileDescriptor fd;
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!fd.OpenReadOnly(full_path)) {
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error->Format("Error opening file '%s'", full_path);
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (fd.SeekTo(offset) == -1) {
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error->Format("Error seeking to %d in file '%s'", offset, full_path);
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedBuffer buffer(bytes);
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const ssize_t bytes_read = fd.Read(buffer.Get(), bytes);
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (static_cast<size_t>(bytes_read) != bytes) {
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error->Format("Error reading %d bytes from file '%s'", bytes, full_path);
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fd.Close();
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint8_t* packed_data = buffer.Release();
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return packed_data;
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif  // __arm__
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); }
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SharedLibrary::~SharedLibrary() {
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Ensure the library is unmapped on destruction.
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (view_.load_address())
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size());
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifdef __arm__
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  delete [] arm_packed_relocs_;
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::Load(const char* full_path,
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         size_t load_address,
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         size_t file_offset,
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         Error* error) {
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // First, record the path.
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: full path '%s'\n", __FUNCTION__, full_path);
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t full_path_len = strlen(full_path);
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (full_path_len >= sizeof(full_path_)) {
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error->Format("Path too long: %s", full_path);
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  strlcpy(full_path_, full_path, sizeof(full_path_));
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base_name_ = GetBaseNamePtr(full_path_);
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Load the ELF binary in memory.
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Loading ELF segments for %s\n", __FUNCTION__, base_name_);
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  {
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ElfLoader loader;
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!loader.LoadAt(full_path_, file_offset, load_address, error)) {
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!view_.InitUnmapped(loader.load_start(),
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            loader.loaded_phdr(),
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            loader.phdr_count(),
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            error)) {
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!symbols_.Init(&view_)) {
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *error = "Missing or malformed symbol table";
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (phdr_table_get_relro_info(view_.phdr(),
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                view_.phdr_count(),
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                view_.load_bias(),
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                &relro_start_,
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                &relro_size_) < 0) {
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    relro_start_ = 0;
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    relro_size_ = 0;
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_);
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  (void)phdr_table_get_arm_exidx(
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_);
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  off_t arm_packed_relocs_offset = 0;
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t arm_packed_relocs_size = 0;
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_);
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ElfView::DynamicIterator dyn(&view_);
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (; dyn.HasNext(); dyn.GetNext()) {
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ELF::Addr dyn_value = dyn.GetValue();
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    uintptr_t dyn_addr = dyn.GetAddress(load_bias());
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    switch (dyn.GetTag()) {
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_DEBUG:
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (view_.dynamic_flags() & PF_W) {
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          *dyn.GetValuePointer() =
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress());
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_INIT:
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_INIT addr=%p\n", dyn_addr);
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FINI:
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_FINI addr=%p\n", dyn_addr);
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_INIT_ARRAY:
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_INIT_ARRAY addr=%p\n", dyn_addr);
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_INIT_ARRAYSZ:
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        init_array_count_ = dyn_value / sizeof(ELF::Addr);
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_INIT_ARRAYSZ value=%p count=%p\n",
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            dyn_value,
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            init_array_count_);
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FINI_ARRAY:
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_FINI_ARRAY addr=%p\n", dyn_addr);
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FINI_ARRAYSZ:
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        fini_array_count_ = dyn_value / sizeof(ELF::Addr);
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_FINI_ARRAYSZ value=%p count=%p\n",
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            dyn_value,
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            fini_array_count_);
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_PREINIT_ARRAY:
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_PREINIT_ARRAY addr=%p\n", dyn_addr);
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_PREINIT_ARRAYSZ:
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        preinit_array_count_ = dyn_value / sizeof(ELF::Addr);
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_PREINIT_ARRAYSZ value=%p count=%p\n",
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            dyn_value,
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            preinit_array_count_);
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_SYMBOLIC:
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_SYMBOLIC\n");
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        has_DT_SYMBOLIC_ = true;
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FLAGS:
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (dyn_value & DF_SYMBOLIC)
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          has_DT_SYMBOLIC_ = true;
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(__arm__)
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case DT_ANDROID_REL_OFFSET:
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        arm_packed_relocs_offset = dyn.GetOffset();
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        LOG("  DT_ANDROID_REL_OFFSET addr=%p\n", arm_packed_relocs_offset);
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        break;
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case DT_ANDROID_REL_SIZE:
348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        arm_packed_relocs_size = dyn.GetValue();
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        LOG("  DT_ANDROID_REL_SIZE=%d\n", arm_packed_relocs_size);
350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        break;
351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(__mips__)
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_MIPS_RLD_MAP:
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        *dyn.GetValuePointer() =
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress());
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      default:
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ;
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifdef __arm__
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // If ARM packed relocations are present in the target library, read the
365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // section data and save it in arm_packed_relocs_.
366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (arm_packed_relocs_offset && arm_packed_relocs_size) {
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG("%s: ARM packed relocations found at offset %d, %d bytes\n",
368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        __FUNCTION__,
369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        arm_packed_relocs_offset,
370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        arm_packed_relocs_size);
371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    arm_packed_relocs_ =
373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ReadArmPackedRelocs(full_path,
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            arm_packed_relocs_offset + file_offset,
375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            arm_packed_relocs_size,
376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            error);
377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!arm_packed_relocs_)
378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG("%s: ARM packed relocations stored at %p\n",
381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        __FUNCTION__,
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        arm_packed_relocs_);
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_);
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::Relocate(LibraryList* lib_list,
391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             Vector<LibraryView*>* dependencies,
392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             Error* error) {
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Apply relocations.
394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_);
395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ElfRelocations relocations;
397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relocations.Init(&view_, error))
399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifdef __arm__
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  relocations.RegisterArmPackedRelocs(arm_packed_relocs_);
403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedLibraryResolver resolver(this, lib_list, dependencies);
406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relocations.ApplyAll(&symbols_, &resolver, error))
407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_);
410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) {
414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return symbols_.LookupByName(symbol_name);
415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) {
418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return symbols_.LookupAddressByName(symbol_name, view_.load_bias());
419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::CreateSharedRelro(size_t load_address,
422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      size_t* relro_start,
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      size_t* relro_size,
424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      int* relro_fd,
425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      Error* error) {
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedRelro relro;
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relro.Allocate(relro_size_, base_name_, error))
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (load_address != 0 && load_address != this->load_address()) {
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Need to relocate the content of the ashmem region first to accomodate
433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // for the new load address.
434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!relro.CopyFromRelocated(
435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             &view_, load_address, relro_start_, relro_size_, error))
436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Simply copy, no relocations.
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!relro.CopyFrom(relro_start_, relro_size_, error))
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Enforce read-only mode for the region's content.
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relro.ForceReadOnly(error))
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // All good.
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *relro_start = relro.start();
449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *relro_size = relro.size();
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *relro_fd = relro.DetachFd();
451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::UseSharedRelro(size_t relro_start,
455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   size_t relro_size,
456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   int relro_fd,
457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   Error* error) {
458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: relro_start=%p relro_size=%p relro_fd=%d\n",
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      __FUNCTION__,
460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (void*)relro_start,
461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (void*)relro_size,
462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      relro_fd);
463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
464f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (relro_fd < 0 || relro_size == 0) {
465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Nothing to do here.
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Sanity check: A shared RELRO is not already used.
470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (relro_used_) {
471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *error = "Library already using shared RELRO section";
472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Sanity check: RELRO addresses must match.
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (relro_start_ != relro_start || relro_size_ != relro_size) {
477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error->Format("RELRO mismatch addr=%p size=%p (wanted addr=%p size=%p)",
478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_start_,
479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_size_,
480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_start,
481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_size);
482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Everything's good, swap pages in this process's address space.
486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedRelro relro;
487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relro.InitFrom(relro_start, relro_size, relro_fd, error))
488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  relro_used_ = true;
491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SharedLibrary::CallConstructors() {
495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CallFunction(init_func_, "DT_INIT");
496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t n = 0; n < init_array_count_; ++n)
497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CallFunction(init_array_[n], "DT_INIT_ARRAY");
498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SharedLibrary::CallDestructors() {
501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t n = fini_array_count_; n > 0; --n) {
502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY");
503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CallFunction(fini_func_, "DT_FINI");
505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::SetJavaVM(void* java_vm,
508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              int minimum_jni_version,
509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              Error* error) {
510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (java_vm == NULL)
511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Lookup for JNI_OnLoad, exit if it doesn't exist.
514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  JNI_OnLoadFunctionPtr jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>(
515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      FindAddressForSymbol("JNI_OnLoad"));
516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!jni_onload)
517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int jni_version = (*jni_onload)(java_vm, NULL);
520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (jni_version < minimum_jni_version) {
521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error->Format("JNI_OnLoad() in %s returned %d, expected at least %d",
522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  full_path_,
523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  jni_version,
524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  minimum_jni_version);
525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Save the JavaVM handle for unload time.
529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  java_vm_ = java_vm;
530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SharedLibrary::CallJniOnUnload() {
534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!java_vm_)
535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  JNI_OnUnloadFunctionPtr jni_on_unload =
538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      reinterpret_cast<JNI_OnUnloadFunctionPtr>(
539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          this->FindAddressForSymbol("JNI_OnUnload"));
540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (jni_on_unload)
542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    (*jni_on_unload)(java_vm_, NULL);
543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::DependencyIterator::GetNext() {
546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  dep_name_ = NULL;
547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (; iter_.HasNext(); iter_.GetNext()) {
548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (iter_.GetTag() == DT_NEEDED) {
549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dep_name_ = symbols_->GetStringById(iter_.GetValue());
550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      iter_.GetNext();
551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return false;
555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace crazy
558