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_library_list.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <dlfcn.h>
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_debug.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_library_view.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_globals.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_rdebug.h"
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_shared_library.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_system.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crazy_linker_util.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crazy_linker_zip.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy {
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A helper struct used when looking up symbols in libraries.
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)struct SymbolLookupState {
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void* found_addr;
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void* weak_addr;
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int weak_count;
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SymbolLookupState() : found_addr(NULL), weak_addr(NULL), weak_count(0) {}
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Check a symbol entry.
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool CheckSymbol(const char* symbol, SharedLibrary* lib) {
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ELF::Sym* entry = lib->LookupSymbolEntry(symbol);
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!entry)
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    void* address = reinterpret_cast<void*>(lib->load_bias() + entry->st_value);
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If this is a strong symbol, record it and return true.
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (ELF_ST_BIND(entry->st_info) == STB_GLOBAL) {
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      found_addr = address;
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If this is a weak symbol, record the first one and
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // increment the weak_count.
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (++weak_count == 1)
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      weak_addr = address;
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)LibraryList::LibraryList() : head_(0), count_(0), has_error_(false) {
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Nothing for now
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)LibraryList::~LibraryList() {
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Invalidate crazy library list.
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  head_ = NULL;
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Destroy all known libraries.
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (!known_libraries_.IsEmpty()) {
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap = known_libraries_.PopLast();
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    delete wrap;
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)LibraryView* LibraryList::FindLibraryByName(const char* lib_name) {
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Sanity check.
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!lib_name)
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return NULL;
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t n = 0; n < known_libraries_.GetCount(); ++n) {
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap = known_libraries_[n];
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!strcmp(lib_name, wrap->GetName()))
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return wrap;
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return NULL;
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void* LibraryList::FindSymbolFrom(const char* symbol_name, LibraryView* from) {
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SymbolLookupState lookup_state;
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!from)
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return NULL;
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Use a work-queue and a set to ensure to perform a breadth-first
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // search.
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Vector<LibraryView*> work_queue;
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Set<LibraryView*> visited_set;
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  work_queue.PushBack(from);
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (!work_queue.IsEmpty()) {
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* lib = work_queue.PopFirst();
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (lib->IsCrazy()) {
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (lookup_state.CheckSymbol(symbol_name, lib->GetCrazy()))
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return lookup_state.found_addr;
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else if (lib->IsSystem()) {
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // TODO(digit): Support weak symbols in system libraries.
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // With the current code, all symbols in system libraries
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // are assumed to be non-weak.
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      void* addr = lib->LookupSymbol(symbol_name);
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (addr)
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return addr;
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If this is a crazy library, add non-visited dependencies
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // to the work queue.
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (lib->IsCrazy()) {
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SharedLibrary::DependencyIterator iter(lib->GetCrazy());
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      while (iter.GetNext()) {
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        LibraryView* dependency = FindKnownLibrary(iter.GetName());
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (dependency && !visited_set.Has(dependency)) {
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          work_queue.PushBack(dependency);
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          visited_set.Add(dependency);
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (lookup_state.weak_count >= 1) {
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // There was at least a single weak symbol definition, so use
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // the first one found in breadth-first search order.
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return lookup_state.weak_addr;
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // There was no symbol definition.
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return NULL;
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)LibraryView* LibraryList::FindLibraryForAddress(void* address) {
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Linearly scan all libraries, looking for one that contains
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // a given address. NOTE: This doesn't check that this falls
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // inside one of the mapped library segments.
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t n = 0; n < known_libraries_.GetCount(); ++n) {
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap = known_libraries_[n];
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // TODO(digit): Search addresses inside system libraries.
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (wrap->IsCrazy()) {
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SharedLibrary* lib = wrap->GetCrazy();
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (lib->ContainsAddress(address))
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return wrap;
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return NULL;
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)_Unwind_Ptr LibraryList::FindArmExIdx(void* pc, int* count) {
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (SharedLibrary* lib = head_; lib; lib = lib->list_next_) {
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (lib->ContainsAddress(pc)) {
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *count = static_cast<int>(lib->arm_exidx_count_);
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return reinterpret_cast<_Unwind_Ptr>(lib->arm_exidx_);
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *count = 0;
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return NULL;
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else  // !__arm__
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)int LibraryList::IteratePhdr(PhdrIterationCallback callback, void* data) {
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int result = 0;
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (SharedLibrary* lib = head_; lib; lib = lib->list_next_) {
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    dl_phdr_info info;
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    info.dlpi_addr = lib->link_map_.l_addr;
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    info.dlpi_name = lib->link_map_.l_name;
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    info.dlpi_phdr = lib->phdr();
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    info.dlpi_phnum = lib->phdr_count();
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    result = callback(&info, sizeof(info), data);
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (result)
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return result;
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif  // !__arm__
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void LibraryList::UnloadLibrary(LibraryView* wrap) {
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Sanity check.
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: for %s (ref_count=%d)\n",
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      __FUNCTION__,
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      wrap->GetName(),
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      wrap->ref_count());
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!wrap->IsSystem() && !wrap->IsCrazy())
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!wrap->SafeDecrementRef())
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If this is a crazy library, perform manual cleanup first.
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (wrap->IsCrazy()) {
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SharedLibrary* lib = wrap->GetCrazy();
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Remove from internal list of crazy libraries.
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (lib->list_next_)
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      lib->list_next_->list_prev_ = lib->list_prev_;
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (lib->list_prev_)
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      lib->list_prev_->list_next_ = lib->list_next_;
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (lib == head_)
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      head_ = lib->list_next_;
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Call JNI_OnUnload, if necessary, then the destructors.
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    lib->CallJniOnUnload();
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    lib->CallDestructors();
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Unload the dependencies recursively.
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SharedLibrary::DependencyIterator iter(lib);
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    while (iter.GetNext()) {
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LibraryView* dependency = FindKnownLibrary(iter.GetName());
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (dependency)
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        UnloadLibrary(dependency);
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Tell GDB of this removal.
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Globals::GetRDebug()->DelEntry(&lib->link_map_);
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  known_libraries_.Remove(wrap);
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Delete the wrapper, which will delete the crazy library, or
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // dlclose() the system one.
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  delete wrap;
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)LibraryView* LibraryList::LoadLibrary(const char* lib_name,
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      int dlopen_mode,
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      uintptr_t load_address,
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      off_t file_offset,
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      SearchPathList* search_path_list,
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      Error* error) {
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* base_name = GetBaseNamePtr(lib_name);
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: lib_name='%s'\n", __FUNCTION__, lib_name);
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // First check whether a library with the same base name was
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // already loaded.
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LibraryView* wrap = FindKnownLibrary(lib_name);
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (wrap) {
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (load_address) {
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Check that this is a crazy library and that is was loaded at
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // the correct address.
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!wrap->IsCrazy()) {
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        error->Format("System library can't be loaded at fixed address %08x",
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      load_address);
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return NULL;
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      uintptr_t actual_address = wrap->GetCrazy()->load_address();
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (actual_address != load_address) {
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        error->Format("Library already loaded at @%08x, can't load it at @%08x",
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      actual_address,
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      load_address);
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return NULL;
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    wrap->AddRef();
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return wrap;
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (IsSystemLibrary(lib_name)) {
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // This is a system library, probably because we're loading the
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // library as a dependency.
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG("%s: Loading system library '%s'\n", __FUNCTION__, lib_name);
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ::dlerror();
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    void* system_lib = dlopen(lib_name, dlopen_mode);
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!system_lib) {
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      error->Format("Can't load system library %s: %s", lib_name, ::dlerror());
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return NULL;
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap = new LibraryView();
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    wrap->SetSystem(system_lib, lib_name);
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    known_libraries_.PushBack(wrap);
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG("%s: System library %s loaded at %p\n", __FUNCTION__, lib_name, wrap);
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG("  name=%s\n", wrap->GetName());
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return wrap;
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedPtr<SharedLibrary> lib(new SharedLibrary());
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Find the full library path.
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String full_path;
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!strchr(lib_name, '/')) {
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG("%s: Looking through the search path list\n", __FUNCTION__);
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const char* path = search_path_list->FindFile(lib_name);
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!path) {
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      error->Format("Can't find library file %s", lib_name);
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return NULL;
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    full_path = path;
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (lib_name[0] != '/') {
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Need to transform this into a full path.
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      full_path = GetCurrentDirectory();
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (full_path.size() && full_path[full_path.size() - 1] != '/')
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        full_path += '/';
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      full_path += lib_name;
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Absolute path. Easy.
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      full_path = lib_name;
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG("%s: Full library path: %s\n", __FUNCTION__, full_path.c_str());
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!PathIsFile(full_path.c_str())) {
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      error->Format("Library file doesn't exist: %s", full_path.c_str());
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return NULL;
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Load the library
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!lib->Load(full_path.c_str(), load_address, file_offset, error))
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return NULL;
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Load all dependendent libraries.
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Loading dependencies of %s\n", __FUNCTION__, base_name);
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SharedLibrary::DependencyIterator iter(lib.Get());
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Vector<LibraryView*> dependencies;
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (iter.GetNext()) {
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Error dep_error;
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* dependency = LoadLibrary(iter.GetName(),
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          dlopen_mode,
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          0U /* load address */,
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          0U /* file offset */,
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          search_path_list,
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          &dep_error);
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!dependency) {
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      error->Format("When loading %s: %s", base_name, dep_error.c_str());
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return NULL;
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    dependencies.PushBack(dependency);
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (CRAZY_DEBUG) {
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG("%s: Dependencies loaded for %s\n", __FUNCTION__, base_name);
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (size_t n = 0; n < dependencies.GetCount(); ++n)
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      LOG("  ... %p %s\n", dependencies[n], dependencies[n]->GetName());
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG("    dependencies @%p\n", &dependencies);
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Relocate the library.
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Relocating %s\n", __FUNCTION__, base_name);
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!lib->Relocate(this, &dependencies, error))
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return NULL;
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Notify GDB of load.
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  lib->link_map_.l_addr = lib->load_address();
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  lib->link_map_.l_name = const_cast<char*>(lib->base_name_);
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  lib->link_map_.l_ld = reinterpret_cast<uintptr_t>(lib->view_.dynamic());
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Globals::GetRDebug()->AddEntry(&lib->link_map_);
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // The library was properly loaded, add it to the list of crazy
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // libraries. IMPORTANT: Do this _before_ calling the constructors
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // because these could call dlopen().
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  lib->list_next_ = head_;
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  lib->list_prev_ = NULL;
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (head_)
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    head_->list_prev_ = lib.Get();
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  head_ = lib.Get();
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Then create a new LibraryView for it.
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  wrap = new LibraryView();
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  wrap->SetCrazy(lib.Get(), lib_name);
363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  known_libraries_.PushBack(wrap);
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Running constructors for %s\n", __FUNCTION__, base_name);
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Now run the constructors.
368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  lib->CallConstructors();
369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG("%s: Done loading %s\n", __FUNCTION__, base_name);
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  lib.Release();
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return wrap;
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// We identify the abi tag for which the linker is running. This allows
377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// us to select the library which matches the abi of the linker.
378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(__arm__) && defined(__ARM_ARCH_7A__)
380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define CURRENT_ABI "armeabi-v7a"
381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(__arm__)
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define CURRENT_ABI "armeabi"
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(__i386__)
384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define CURRENT_ABI "x86"
385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(__mips__)
386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define CURRENT_ABI "mips"
387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(__x86_64__)
388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define CURRENT_ABI "x86_64"
389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(__aarch64__)
390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define CURRENT_ABI "arm64-v8a"
391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#else
392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#error "Unsupported target abi"
393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst size_t kMaxFilenameInZip = 256;
396116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst size_t kPageSize = 4096;
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
398116680a4aac90f2aa7413d9095a592090648e557Ben MurdochLibraryView* LibraryList::LoadLibraryInZipFile(const char* zip_file_path,
399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               const char* lib_name,
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               int dlopen_flags,
401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               uintptr_t load_address,
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               SearchPathList* search_path_list,
403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               Error* error) {
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  String fullname;
405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fullname.Reserve(kMaxFilenameInZip);
406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fullname = "lib/";
407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fullname += CURRENT_ABI;
408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fullname += "/crazy.";
409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  fullname += lib_name;
410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (fullname.size() + 1 > kMaxFilenameInZip) {
412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error->Format("Filename too long for a file in a zip file %s\n",
413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                  fullname.c_str());
414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int offset = FindStartOffsetOfFileInZipFile(zip_file_path, fullname.c_str());
418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (offset == -1) {
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if ((offset & (kPageSize - 1)) != 0) {
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error->Format("Library %s is not page aligned in zipfile %s\n",
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                  lib_name, zip_file_path);
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return LoadLibrary(
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      zip_file_path, dlopen_flags, load_address, offset,
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      search_path_list, error);
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void LibraryList::AddLibrary(LibraryView* wrap) {
434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  known_libraries_.PushBack(wrap);
435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)LibraryView* LibraryList::FindKnownLibrary(const char* name) {
438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* base_name = GetBaseNamePtr(name);
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t n = 0; n < known_libraries_.GetCount(); ++n) {
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap = known_libraries_[n];
441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!strcmp(base_name, wrap->GetName()))
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return wrap;
443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return NULL;
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace crazy
448