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)// Implements the crazy linker C-based API exposed by <crazy_linker.h>
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <crazy_linker.h>
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string.h>
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_error.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_ashmem.h"
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_globals.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_proc_maps.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_search_path_list.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_shared_library.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_thread.h"
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_util.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_library_view.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_system.h"
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using crazy::Globals;
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using crazy::Error;
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using crazy::SearchPathList;
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using crazy::ScopedGlobalLock;
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using crazy::LibraryView;
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// crazy_context_t
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)struct crazy_context_t {
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  crazy_context_t()
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : load_address(0),
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        file_offset(0),
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        error(),
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        search_paths(),
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        java_vm(NULL),
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        minimum_jni_version(0),
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        callback_poster(NULL),
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        callback_poster_opaque(NULL) {
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ResetSearchPaths();
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void ResetSearchPaths();
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t load_address;
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t file_offset;
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Error error;
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SearchPathList search_paths;
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void* java_vm;
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int minimum_jni_version;
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  crazy_callback_poster_t callback_poster;
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void* callback_poster_opaque;
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_t::ResetSearchPaths() {
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  search_paths.ResetFromEnv("LD_LIBRARY_PATH");
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// API functions
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)extern "C" {
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_context_t* crazy_context_create(void) { return new crazy_context_t(); }
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char* crazy_context_get_error(crazy_context_t* context) {
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* error = context->error.c_str();
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return (error[0] != '\0') ? error : NULL;
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Clear error in a given context.
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_clear_error(crazy_context_t* context) {
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->error = "";
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_load_address(crazy_context_t* context,
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                    size_t load_address) {
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->load_address = load_address;
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)size_t crazy_context_get_load_address(crazy_context_t* context) {
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return context->load_address;
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_file_offset(crazy_context_t* context,
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   size_t file_offset) {
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->file_offset = file_offset;
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)size_t crazy_context_get_file_offset(crazy_context_t* context) {
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return context->file_offset;
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_context_add_search_path(crazy_context_t* context,
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                             const char* file_path) {
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->search_paths.AddPaths(file_path);
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_SUCCESS;
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_context_add_search_path_for_address(
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    crazy_context_t* context,
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    void* address) {
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uintptr_t load_address;
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char path[512];
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char* p;
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (crazy::FindElfBinaryForAddress(
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          address, &load_address, path, sizeof(path)) &&
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (p = strrchr(path, '/')) != NULL && p[1]) {
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *p = '\0';
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return crazy_context_add_search_path(context, path);
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->error.Format("Could not find ELF binary at address @%p", address);
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_FAILURE;
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_reset_search_paths(crazy_context_t* context) {
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->ResetSearchPaths();
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_java_vm(crazy_context_t* context,
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               void* java_vm,
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               int minimum_jni_version) {
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->java_vm = java_vm;
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->minimum_jni_version = minimum_jni_version;
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_get_java_vm(crazy_context_t* context,
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               void** java_vm,
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               int* minimum_jni_version) {
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *java_vm = context->java_vm;
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *minimum_jni_version = context->minimum_jni_version;
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_callback_poster(crazy_context_t* context,
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       crazy_callback_poster_t poster,
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       void* poster_opaque) {
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->callback_poster = poster;
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context->callback_poster_opaque = poster_opaque;
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_get_callback_poster(crazy_context_t* context,
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       crazy_callback_poster_t* poster,
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       void** poster_opaque) {
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *poster = context->callback_poster;
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *poster_opaque = context->callback_poster_opaque;
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_callback_run(crazy_callback_t* callback) {
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  (*callback->handler)(callback->opaque);
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_destroy(crazy_context_t* context) { delete context; }
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Scoped delayed execution, removes RDebug callbacks on scope exit.  No-op
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// if callback is NULL.
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ScopedDelayedCallbackPoster {
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedDelayedCallbackPoster(crazy_context_t* context) {
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (context && context->callback_poster) {
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      crazy::Globals::GetRDebug()->SetDelayedCallbackPoster(&PostFromContext,
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                            context);
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      set_delayed_callback_poster_ = true;
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      set_delayed_callback_poster_ = false;
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ~ScopedDelayedCallbackPoster() {
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (set_delayed_callback_poster_)
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      crazy::Globals::GetRDebug()->SetDelayedCallbackPoster(NULL, NULL);
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Wrap callback hander and opaque into a call to a crazy_context_poster_t.
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  static bool PostFromContext(void* crazy_context,
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              crazy_callback_handler_t handler,
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              void* opaque) {
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    crazy_context_t* context = static_cast<crazy_context_t*>(crazy_context);
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    crazy_callback_t callback;
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    callback.handler = handler;
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    callback.opaque = opaque;
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return context->callback_poster(&callback,
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                    context->callback_poster_opaque);
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // True if the context offered a callback_poster, otherwise false.
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool set_delayed_callback_poster_;
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_open(crazy_library_t** library,
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                  const char* lib_name,
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                  crazy_context_t* context) {
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedDelayedCallbackPoster poster(context);
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedGlobalLock lock;
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LibraryView* wrap =
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      crazy::Globals::GetLibraries()->LoadLibrary(lib_name,
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                  RTLD_NOW,
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                  context->load_address,
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                  context->file_offset,
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                  &context->search_paths,
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                  &context->error);
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!wrap)
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (context->java_vm != NULL && wrap->IsCrazy()) {
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    crazy::SharedLibrary* lib = wrap->GetCrazy();
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!lib->SetJavaVM(
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             context->java_vm, context->minimum_jni_version, &context->error)) {
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      crazy::Globals::GetLibraries()->UnloadLibrary(wrap);
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return CRAZY_STATUS_FAILURE;
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *library = reinterpret_cast<crazy_library_t*>(wrap);
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_SUCCESS;
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdochcrazy_status_t crazy_library_open_in_zip_file(crazy_library_t** library,
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                              const char* zipfile_name,
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                              const char* lib_name,
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                              crazy_context_t* context) {
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedDelayedCallbackPoster poster(context);
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedGlobalLock lock;
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LibraryView* wrap =
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crazy::Globals::GetLibraries()->LoadLibraryInZipFile(
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          zipfile_name,
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          lib_name,
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          RTLD_NOW,
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          context->load_address,
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          &context->search_paths,
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          &context->error);
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!wrap)
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return CRAZY_STATUS_FAILURE;
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (context->java_vm != NULL && wrap->IsCrazy()) {
246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    crazy::SharedLibrary* lib = wrap->GetCrazy();
247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!lib->SetJavaVM(
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch             context->java_vm, context->minimum_jni_version, &context->error)) {
249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crazy::Globals::GetLibraries()->UnloadLibrary(wrap);
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return CRAZY_STATUS_FAILURE;
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *library = reinterpret_cast<crazy_library_t*>(wrap);
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return CRAZY_STATUS_SUCCESS;
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_get_info(crazy_library_t* library,
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      crazy_context_t* context,
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      crazy_library_info_t* info) {
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!library) {
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    context->error = "Invalid library file handle";
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LibraryView* wrap = reinterpret_cast<LibraryView*>(library);
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!wrap->GetInfo(&info->load_address,
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     &info->load_size,
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     &info->relro_start,
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     &info->relro_size,
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     &context->error)) {
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_SUCCESS;
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_system_can_share_relro(void) {
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  crazy::AshmemRegion region;
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!region.Allocate(PAGE_SIZE, NULL) ||
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      !region.SetProtectionFlags(PROT_READ) ||
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      !crazy::AshmemRegion::CheckFileDescriptorIsReadOnly(region.fd()))
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_SUCCESS;
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_create_shared_relro(crazy_library_t* library,
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                 crazy_context_t* context,
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                 size_t load_address,
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                 size_t* relro_start,
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                 size_t* relro_size,
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                 int* relro_fd) {
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LibraryView* wrap = reinterpret_cast<LibraryView*>(library);
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!library || !wrap->IsCrazy()) {
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    context->error = "Invalid library file handle";
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  crazy::SharedLibrary* lib = wrap->GetCrazy();
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!lib->CreateSharedRelro(
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           load_address, relro_start, relro_size, relro_fd, &context->error))
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_SUCCESS;
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_use_shared_relro(crazy_library_t* library,
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              crazy_context_t* context,
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              size_t relro_start,
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              size_t relro_size,
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              int relro_fd) {
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LibraryView* wrap = reinterpret_cast<LibraryView*>(library);
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!library || !wrap->IsCrazy()) {
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    context->error = "Invalid library file handle";
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  crazy::SharedLibrary* lib = wrap->GetCrazy();
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!lib->UseSharedRelro(relro_start, relro_size, relro_fd, &context->error))
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_FAILURE;
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_SUCCESS;
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_find_by_name(const char* library_name,
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          crazy_library_t** library) {
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  {
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ScopedGlobalLock lock;
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap =
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        Globals::GetLibraries()->FindLibraryByName(library_name);
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!wrap)
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return CRAZY_STATUS_FAILURE;
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    wrap->AddRef();
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *library = reinterpret_cast<crazy_library_t*>(wrap);
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_SUCCESS;
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_find_symbol(crazy_library_t* library,
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         const char* symbol_name,
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         void** symbol_address) {
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LibraryView* wrap = reinterpret_cast<LibraryView*>(library);
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(digit): Handle NULL symbols properly.
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *symbol_address = wrap->LookupSymbol(symbol_name);
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return (*symbol_address == NULL) ? CRAZY_STATUS_FAILURE
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   : CRAZY_STATUS_SUCCESS;
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_linker_find_symbol(const char* symbol_name,
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        void** symbol_address) {
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(digit): Implement this.
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return CRAZY_STATUS_FAILURE;
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_find_from_address(void* address,
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                               crazy_library_t** library) {
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  {
363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ScopedGlobalLock lock;
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap = Globals::GetLibraries()->FindLibraryForAddress(address);
365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!wrap)
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return CRAZY_STATUS_FAILURE;
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    wrap->AddRef();
369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *library = reinterpret_cast<crazy_library_t*>(wrap);
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return CRAZY_STATUS_SUCCESS;
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_library_close(crazy_library_t* library) {
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  crazy_library_close_with_context(library, NULL);
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_library_close_with_context(crazy_library_t* library,
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      crazy_context_t* context) {
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (library) {
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ScopedDelayedCallbackPoster poster(context);
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ScopedGlobalLock lock;
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LibraryView* wrap = reinterpret_cast<LibraryView*>(library);
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Globals::GetLibraries()->UnloadLibrary(wrap);
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // extern "C"
391