crazy_linker_shared_library.cpp revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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)
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy {
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef SharedLibrary::linker_function_t linker_function_t;
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved);
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved);
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Call a constructor or destructor function pointer. Ignore
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NULL and -1 values intentionally. They correspond to markers
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// in the tables, or deleted values.
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |func_type| corresponds to the type of the function, and is only
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// used for debugging (examples are "DT_INIT", "DT_INIT_ARRAY", etc...).
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void CallFunction(linker_function_t func, const char* func_type) {
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uintptr_t func_address = reinterpret_cast<uintptr_t>(func);
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: %p %s\n", __FUNCTION__, func, func_type);
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (func_address != 0 && func_address != uintptr_t(-1))
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    func();
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// An instance of ElfRelocator::SymbolResolver that can be used
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to resolve symbols in a shared library being loaded by
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// LibraryList::LoadLibrary.
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class SharedLibraryResolver : public ElfRelocations::SymbolResolver {
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedLibraryResolver(SharedLibrary* lib,
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        LibraryList* lib_list,
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        Vector<LibraryView*>* dependencies)
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : lib_(lib), dependencies_(dependencies) {}
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void* Lookup(const char* symbol_name) {
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // TODO(digit): Add the ability to lookup inside the main executable.
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // First, look inside the current library.
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name);
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (entry)
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value);
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Special case: redirect the dynamic linker symbols to our wrappers.
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // This ensures that loaded libraries can call dlopen() / dlsym()
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // and transparently use the crazy linker to perform their duty.
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    void* address = WrapLinkerSymbol(symbol_name);
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (address)
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return address;
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Then look inside the dependencies.
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (size_t n = 0; n < dependencies_->GetCount(); ++n) {
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LibraryView* wrap = (*dependencies_)[n];
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // LOG("%s: Looking into dependency %p (%s)\n", __FUNCTION__, wrap,
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // wrap->GetName());
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (wrap->IsSystem()) {
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        address = ::dlsym(wrap->GetSystem(), symbol_name);
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // Android libm.so defines isnanf as weak. This means that its
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // address cannot be found by dlsym(), which always returns NULL
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // for weak symbols. However, libm.so contains the real isnanf
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // as __isnanf. If we encounter isnanf and fail to resolve it in
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // libm.so, retry with __isnanf.
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        //
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // This occurs only in clang, which lacks __builtin_isnanf. The
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // gcc compiler implements isnanf as a builtin, so the symbol
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // isnanf never need be resolved in gcc builds.
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        //
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // http://code.google.com/p/chromium/issues/detail?id=376828
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (!address &&
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            !strcmp(symbol_name, "isnanf") &&
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            !strcmp(wrap->GetName(), "libm.so"))
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          address = ::dlsym(wrap->GetSystem(), "__isnanf");
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (address)
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          return address;
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (wrap->IsCrazy()) {
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        SharedLibrary* dep = wrap->GetCrazy();
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        entry = dep->LookupSymbolEntry(symbol_name);
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (entry)
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          return reinterpret_cast<void*>(dep->load_bias() + entry->st_value);
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Nothing found here.
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return NULL;
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedLibrary* lib_;
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Vector<LibraryView*>* dependencies_;
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); }
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SharedLibrary::~SharedLibrary() {
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Ensure the library is unmapped on destruction.
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (view_.load_address())
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size());
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::Load(const char* full_path,
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         size_t load_address,
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         size_t file_offset,
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         Error* error) {
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // First, record the path.
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: full path '%s'\n", __FUNCTION__, full_path);
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t full_path_len = strlen(full_path);
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (full_path_len >= sizeof(full_path_)) {
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error->Format("Path too long: %s", full_path);
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  strlcpy(full_path_, full_path, sizeof(full_path_));
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base_name_ = GetBaseNamePtr(full_path_);
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Load the ELF binary in memory.
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Loading ELF segments for %s\n", __FUNCTION__, base_name_);
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  {
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ElfLoader loader;
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!loader.LoadAt(full_path_, file_offset, load_address, error)) {
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!view_.InitUnmapped(loader.load_start(),
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            loader.loaded_phdr(),
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            loader.phdr_count(),
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            error)) {
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!symbols_.Init(&view_)) {
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *error = "Missing or malformed symbol table";
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (phdr_table_get_relro_info(view_.phdr(),
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                view_.phdr_count(),
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                view_.load_bias(),
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                &relro_start_,
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                &relro_size_) < 0) {
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    relro_start_ = 0;
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    relro_size_ = 0;
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_);
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  (void)phdr_table_get_arm_exidx(
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_);
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_);
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ElfView::DynamicIterator dyn(&view_);
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (; dyn.HasNext(); dyn.GetNext()) {
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ELF::Addr dyn_value = dyn.GetValue();
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    uintptr_t dyn_addr = dyn.GetAddress(load_bias());
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    switch (dyn.GetTag()) {
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_DEBUG:
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (view_.dynamic_flags() & PF_W) {
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          *dyn.GetValuePointer() =
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress());
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_INIT:
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_INIT addr=%p\n", dyn_addr);
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FINI:
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_FINI addr=%p\n", dyn_addr);
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_INIT_ARRAY:
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_INIT_ARRAY addr=%p\n", dyn_addr);
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_INIT_ARRAYSZ:
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        init_array_count_ = dyn_value / sizeof(ELF::Addr);
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_INIT_ARRAYSZ value=%p count=%p\n",
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            dyn_value,
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            init_array_count_);
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FINI_ARRAY:
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_FINI_ARRAY addr=%p\n", dyn_addr);
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FINI_ARRAYSZ:
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        fini_array_count_ = dyn_value / sizeof(ELF::Addr);
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_FINI_ARRAYSZ value=%p count=%p\n",
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            dyn_value,
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            fini_array_count_);
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_PREINIT_ARRAY:
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_PREINIT_ARRAY addr=%p\n", dyn_addr);
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_PREINIT_ARRAYSZ:
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        preinit_array_count_ = dyn_value / sizeof(ELF::Addr);
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_PREINIT_ARRAYSZ value=%p count=%p\n",
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            dyn_value,
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            preinit_array_count_);
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_SYMBOLIC:
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LOG("  DT_SYMBOLIC\n");
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        has_DT_SYMBOLIC_ = true;
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_FLAGS:
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (dyn_value & DF_SYMBOLIC)
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          has_DT_SYMBOLIC_ = true;
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(__mips__)
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case DT_MIPS_RLD_MAP:
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        *dyn.GetValuePointer() =
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress());
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      default:
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ;
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_);
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::Relocate(LibraryList* lib_list,
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             Vector<LibraryView*>* dependencies,
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             Error* error) {
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Apply relocations.
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_);
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ElfRelocations relocations;
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relocations.Init(&view_, error))
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedLibraryResolver resolver(this, lib_list, dependencies);
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relocations.ApplyAll(&symbols_, &resolver, error))
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_);
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) {
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return symbols_.LookupByName(symbol_name);
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) {
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return symbols_.LookupAddressByName(symbol_name, view_.load_bias());
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::CreateSharedRelro(size_t load_address,
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      size_t* relro_start,
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      size_t* relro_size,
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      int* relro_fd,
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      Error* error) {
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedRelro relro;
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relro.Allocate(relro_size_, base_name_, error))
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (load_address != 0 && load_address != this->load_address()) {
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Need to relocate the content of the ashmem region first to accomodate
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // for the new load address.
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!relro.CopyFromRelocated(
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             &view_, load_address, relro_start_, relro_size_, error))
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Simply copy, no relocations.
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!relro.CopyFrom(relro_start_, relro_size_, error))
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Enforce read-only mode for the region's content.
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relro.ForceReadOnly(error))
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // All good.
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *relro_start = relro.start();
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *relro_size = relro.size();
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *relro_fd = relro.DetachFd();
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::UseSharedRelro(size_t relro_start,
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   size_t relro_size,
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   int relro_fd,
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   Error* error) {
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: relro_start=%p relro_size=%p relro_fd=%d\n",
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      __FUNCTION__,
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (void*)relro_start,
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (void*)relro_size,
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      relro_fd);
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (relro_fd < 0 || relro_size == 0) {
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Nothing to do here.
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Sanity check: A shared RELRO is not already used.
363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (relro_used_) {
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *error = "Library already using shared RELRO section";
365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Sanity check: RELRO addresses must match.
369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (relro_start_ != relro_start || relro_size_ != relro_size) {
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error->Format("RELRO mismatch addr=%p size=%p (wanted addr=%p size=%p)",
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_start_,
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_size_,
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_start,
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  relro_size);
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Everything's good, swap pages in this process's address space.
379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedRelro relro;
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!relro.InitFrom(relro_start, relro_size, relro_fd, error))
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  relro_used_ = true;
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SharedLibrary::CallConstructors() {
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CallFunction(init_func_, "DT_INIT");
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t n = 0; n < init_array_count_; ++n)
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CallFunction(init_array_[n], "DT_INIT_ARRAY");
391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SharedLibrary::CallDestructors() {
394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t n = fini_array_count_; n > 0; --n) {
395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY");
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CallFunction(fini_func_, "DT_FINI");
398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::SetJavaVM(void* java_vm,
401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              int minimum_jni_version,
402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              Error* error) {
403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (java_vm == NULL)
404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Lookup for JNI_OnLoad, exit if it doesn't exist.
407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  JNI_OnLoadFunctionPtr jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>(
408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      FindAddressForSymbol("JNI_OnLoad"));
409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!jni_onload)
410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int jni_version = (*jni_onload)(java_vm, NULL);
413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (jni_version < minimum_jni_version) {
414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    error->Format("JNI_OnLoad() in %s returned %d, expected at least %d",
415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  full_path_,
416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  jni_version,
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  minimum_jni_version);
418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Save the JavaVM handle for unload time.
422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  java_vm_ = java_vm;
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SharedLibrary::CallJniOnUnload() {
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!java_vm_)
428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  JNI_OnUnloadFunctionPtr jni_on_unload =
431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      reinterpret_cast<JNI_OnUnloadFunctionPtr>(
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          this->FindAddressForSymbol("JNI_OnUnload"));
433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (jni_on_unload)
435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    (*jni_on_unload)(java_vm_, NULL);
436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedLibrary::DependencyIterator::GetNext() {
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  dep_name_ = NULL;
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (; iter_.HasNext(); iter_.GetNext()) {
441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (iter_.GetTag() == DT_NEEDED) {
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dep_name_ = symbols_->GetStringById(iter_.GetValue());
443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      iter_.GetNext();
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return false;
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace crazy
451