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