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