148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Copyright (c) 2013 The Chromium Authors. All rights reserved. 248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Use of this source code is governed by a BSD-style license that can be 348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// found in the LICENSE file. 448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Implements the crazy linker C-based API exposed by <crazy_linker.h> 648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include <crazy_linker.h> 848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include <string.h> 1048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 1148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_error.h" 1248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_ashmem.h" 1348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_globals.h" 1448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_proc_maps.h" 1548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_search_path_list.h" 1648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_shared_library.h" 1748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_thread.h" 1848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_util.h" 1948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_library_view.h" 2048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_system.h" 2148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 2248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerusing crazy::Globals; 2348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerusing crazy::Error; 2448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerusing crazy::SearchPathList; 2548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerusing crazy::ScopedGlobalLock; 2648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerusing crazy::LibraryView; 2748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 2848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// 2948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// crazy_context_t 3048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// 3148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 3248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerstruct crazy_context_t { 3348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner public: 3448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy_context_t() 3548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner : load_address(0), 3648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner file_offset(0), 3748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner error(), 3848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner search_paths(), 3948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner java_vm(NULL), 406788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin minimum_jni_version(0), 416788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin callback_poster(NULL), 426788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin callback_poster_opaque(NULL) { 4348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ResetSearchPaths(); 4448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 4548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 4648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void ResetSearchPaths(); 4748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 4848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner size_t load_address; 4948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner size_t file_offset; 5048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner Error error; 5148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner SearchPathList search_paths; 5248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void* java_vm; 5348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner int minimum_jni_version; 546788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_callback_poster_t callback_poster; 556788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin void* callback_poster_opaque; 5648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner}; 5748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 5848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_t::ResetSearchPaths() { 5948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner search_paths.ResetFromEnv("LD_LIBRARY_PATH"); 6048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 6148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 6248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// 6348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// API functions 6448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// 6548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 6648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerextern "C" { 6748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 6848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_context_t* crazy_context_create(void) { return new crazy_context_t(); } 6948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 7048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerconst char* crazy_context_get_error(crazy_context_t* context) { 7148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner const char* error = context->error.c_str(); 7248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return (error[0] != '\0') ? error : NULL; 7348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 7448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 7548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Clear error in a given context. 7648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_clear_error(crazy_context_t* context) { 7748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->error = ""; 7848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 7948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 8048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_set_load_address(crazy_context_t* context, 8148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner size_t load_address) { 8248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->load_address = load_address; 8348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 8448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 8548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnersize_t crazy_context_get_load_address(crazy_context_t* context) { 8648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return context->load_address; 8748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 8848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 8948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_set_file_offset(crazy_context_t* context, 9048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner size_t file_offset) { 9148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->file_offset = file_offset; 9248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 9348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 9448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnersize_t crazy_context_get_file_offset(crazy_context_t* context) { 9548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return context->file_offset; 9648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 9748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 9848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_context_add_search_path(crazy_context_t* context, 9948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner const char* file_path) { 10048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->search_paths.AddPaths(file_path); 10148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 10248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 10348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 10448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_context_add_search_path_for_address( 10548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy_context_t* context, 10648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void* address) { 10748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner uintptr_t load_address; 10848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner char path[512]; 10948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner char* p; 11048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 11148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (crazy::FindElfBinaryForAddress( 11248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner address, &load_address, path, sizeof(path)) && 11348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner (p = strrchr(path, '/')) != NULL && p[1]) { 11448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner *p = '\0'; 11548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return crazy_context_add_search_path(context, path); 11648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 11748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 11848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->error.Format("Could not find ELF binary at address @%p", address); 11948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 12048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 12148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 12248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_reset_search_paths(crazy_context_t* context) { 12348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->ResetSearchPaths(); 12448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 12548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 12648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_set_java_vm(crazy_context_t* context, 12748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void* java_vm, 12848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner int minimum_jni_version) { 12948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->java_vm = java_vm; 13048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->minimum_jni_version = minimum_jni_version; 13148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 13248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 13348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_get_java_vm(crazy_context_t* context, 13448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void** java_vm, 13548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner int* minimum_jni_version) { 13648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner *java_vm = context->java_vm; 13748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner *minimum_jni_version = context->minimum_jni_version; 13848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 13948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 1406788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwinvoid crazy_context_set_callback_poster(crazy_context_t* context, 1416788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_callback_poster_t poster, 1426788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin void* poster_opaque) { 1436788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin context->callback_poster = poster; 1446788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin context->callback_poster_opaque = poster_opaque; 1456788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin} 1466788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 1476788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwinvoid crazy_context_get_callback_poster(crazy_context_t* context, 1486788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_callback_poster_t* poster, 1496788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin void** poster_opaque) { 1506788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin *poster = context->callback_poster; 1516788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin *poster_opaque = context->callback_poster_opaque; 1526788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin} 1536788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 1546788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwinvoid crazy_callback_run(crazy_callback_t* callback) { 1556788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin (*callback->handler)(callback->opaque); 1566788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin} 1576788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 15848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_context_destroy(crazy_context_t* context) { delete context; } 15948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 1606788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin// Scoped delayed execution, removes RDebug callbacks on scope exit. No-op 1616788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin// if callback is NULL. 1626788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwinclass ScopedDelayedCallbackPoster { 1636788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin public: 1646788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin ScopedDelayedCallbackPoster(crazy_context_t* context) { 1656788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin if (context && context->callback_poster) { 1666788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy::Globals::GetRDebug()->SetDelayedCallbackPoster(&PostFromContext, 1676788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin context); 1686788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin set_delayed_callback_poster_ = true; 1696788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin } else { 1706788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin set_delayed_callback_poster_ = false; 1716788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin } 1726788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin } 1736788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 1746788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin ~ScopedDelayedCallbackPoster() { 1756788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin if (set_delayed_callback_poster_) 1766788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy::Globals::GetRDebug()->SetDelayedCallbackPoster(NULL, NULL); 1776788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin } 1786788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 1796788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin private: 1806788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin // Wrap callback hander and opaque into a call to a crazy_context_poster_t. 1816788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin static bool PostFromContext(void* crazy_context, 1826788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_callback_handler_t handler, 1836788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin void* opaque) { 1846788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_context_t* context = static_cast<crazy_context_t*>(crazy_context); 1856788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_callback_t callback; 1866788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin callback.handler = handler; 1876788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin callback.opaque = opaque; 1886788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin return context->callback_poster(&callback, 1896788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin context->callback_poster_opaque); 1906788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin } 1916788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 1926788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin // True if the context offered a callback_poster, otherwise false. 1936788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin bool set_delayed_callback_poster_; 1946788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin}; 1956788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 19648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_library_open(crazy_library_t** library, 19748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner const char* lib_name, 19848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy_context_t* context) { 1996788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin ScopedDelayedCallbackPoster poster(context); 20048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ScopedGlobalLock lock; 2016788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 20248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = 20348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy::Globals::GetLibraries()->LoadLibrary(lib_name, 20448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner RTLD_NOW, 20548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->load_address, 20648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->file_offset, 20748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner &context->search_paths, 20848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner &context->error); 2096788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 21048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (!wrap) 21148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 21248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 21348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (context->java_vm != NULL && wrap->IsCrazy()) { 21448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy::SharedLibrary* lib = wrap->GetCrazy(); 21548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (!lib->SetJavaVM( 21648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->java_vm, context->minimum_jni_version, &context->error)) { 21748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy::Globals::GetLibraries()->UnloadLibrary(wrap); 21848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 21948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 22048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 22148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 22248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner *library = reinterpret_cast<crazy_library_t*>(wrap); 22348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 22448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 22548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 22648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_library_get_info(crazy_library_t* library, 22748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy_context_t* context, 22848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy_library_info_t* info) { 22948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (!library) { 23048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->error = "Invalid library file handle"; 23148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 23248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 23348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 23448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = reinterpret_cast<LibraryView*>(library); 23548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (!wrap->GetInfo(&info->load_address, 23648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner &info->load_size, 23748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner &info->relro_start, 23848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner &info->relro_size, 23948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner &context->error)) { 24048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 24148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 24248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 24348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 24448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 24548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 24648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_system_can_share_relro(void) { 24748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy::AshmemRegion region; 24848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (!region.Allocate(PAGE_SIZE, NULL) || 24948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner !region.SetProtectionFlags(PROT_READ) || 250cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner !crazy::AshmemRegion::CheckFileDescriptorIsReadOnly(region.fd())) 25148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 25248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 25348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 25448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 25548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 256cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turnercrazy_status_t crazy_library_create_shared_relro(crazy_library_t* library, 257cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner crazy_context_t* context, 258cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner size_t load_address, 259cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner size_t* relro_start, 260cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner size_t* relro_size, 261cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner int* relro_fd) { 26248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = reinterpret_cast<LibraryView*>(library); 26348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 264cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner if (!library || !wrap->IsCrazy()) { 26548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->error = "Invalid library file handle"; 26648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 26748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 26848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 269cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner crazy::SharedLibrary* lib = wrap->GetCrazy(); 270cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner if (!lib->CreateSharedRelro( 271cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner load_address, relro_start, relro_size, relro_fd, &context->error)) 27248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 27348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 27448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 27548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 27648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 277cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turnercrazy_status_t crazy_library_use_shared_relro(crazy_library_t* library, 278cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner crazy_context_t* context, 279cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner size_t relro_start, 280cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner size_t relro_size, 281cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner int relro_fd) { 28248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = reinterpret_cast<LibraryView*>(library); 28348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 284cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner if (!library || !wrap->IsCrazy()) { 28548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner context->error = "Invalid library file handle"; 28648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 28748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 28848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 289cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner crazy::SharedLibrary* lib = wrap->GetCrazy(); 290cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner if (!lib->UseSharedRelro(relro_start, relro_size, relro_fd, &context->error)) 29148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 29248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 29348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 29448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 29548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 29648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_library_find_by_name(const char* library_name, 29748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy_library_t** library) { 29848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner { 29948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ScopedGlobalLock lock; 30048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = 30148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner Globals::GetLibraries()->FindLibraryByName(library_name); 30248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (!wrap) 30348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 30448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 30548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner wrap->AddRef(); 30648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner *library = reinterpret_cast<crazy_library_t*>(wrap); 30748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 30848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 30948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 31048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 31148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_library_find_symbol(crazy_library_t* library, 31248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner const char* symbol_name, 31348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void** symbol_address) { 31448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = reinterpret_cast<LibraryView*>(library); 31548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 31648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // TODO(digit): Handle NULL symbols properly. 31748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner *symbol_address = wrap->LookupSymbol(symbol_name); 31848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return (*symbol_address == NULL) ? CRAZY_STATUS_FAILURE 31948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner : CRAZY_STATUS_SUCCESS; 32048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 32148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 32248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_linker_find_symbol(const char* symbol_name, 32348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void** symbol_address) { 32448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // TODO(digit): Implement this. 32548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 32648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 32748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 32848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnercrazy_status_t crazy_library_find_from_address(void* address, 32948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner crazy_library_t** library) { 33048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner { 33148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ScopedGlobalLock lock; 33248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = Globals::GetLibraries()->FindLibraryForAddress(address); 33348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (!wrap) 33448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_FAILURE; 33548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 33648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner wrap->AddRef(); 33748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 33848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner *library = reinterpret_cast<crazy_library_t*>(wrap); 33948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner return CRAZY_STATUS_SUCCESS; 34048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 34148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 34248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 34348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnervoid crazy_library_close(crazy_library_t* library) { 3446788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_library_close_with_context(library, NULL); 3456788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin} 3466788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin 3476788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwinvoid crazy_library_close_with_context(crazy_library_t* library, 3486788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin crazy_context_t* context) { 34948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner if (library) { 3506788f450cf7ef93fe2fe0c20ec4b44a38e049bc7Simon Baldwin ScopedDelayedCallbackPoster poster(context); 35148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ScopedGlobalLock lock; 35248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner LibraryView* wrap = reinterpret_cast<LibraryView*>(library); 35348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 35448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner Globals::GetLibraries()->UnloadLibrary(wrap); 35548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner } 35648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} 35748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 35848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} // extern "C" 359