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)#ifndef CRAZY_LINKER_H 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define CRAZY_LINKER_H 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This is the crazy linker, a custom dynamic linker that can be used 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// by NDK applications to load shared libraries (not executables) with 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// a twist. 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Compared to the dynamic linker, the crazy one has the following 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// features: 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - It can use an arbitrary search path. 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - It can load a library at a memory fixed address, or from a fixed 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// file offset (both must be page-aligned). 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - It can share the RELRO section between two libraries 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// loaded at the same address in two distinct processes. 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <dlfcn.h> 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdbool.h> 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stddef.h> 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __cplusplus 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)extern "C" { 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Function attribute to indicate that it needs to be exported by 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the library. 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define _CRAZY_PUBLIC __attribute__((__visibility__("default"))) 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Status values returned by crazy linker functions to indicate 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// success or failure. They were chosen to match boolean values, 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// this allows one to test for failures with: 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// if (!crazy_linker_function(....)) { 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// ... an error occured. 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// } 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// If the function called used a crazy_context_t, it is possible to 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// retrieve the error details with crazy_context_get_error(). 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef enum { 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CRAZY_STATUS_FAILURE = 0, 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CRAZY_STATUS_SUCCESS = 1 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} crazy_status_t; 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Opaque handle to a context object that will hold parameters 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// for the crazy linker's operations. For example, this is where 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// you would set the explicit load address, and other user-provided 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// values before calling functions like crazy_library_open(). 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The context holds a list of library search paths, initialized to 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the content of the LD_LIBRARY_PATH variable on creation. 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The context also holds a string buffer to hold error messages that 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// can be queried with crazy_context_get_error(). 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef struct crazy_context_t crazy_context_t; 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Create a new context object. 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Note that this calls crazy_context_reset_search_paths(). 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_context_t* crazy_context_create(void) _CRAZY_PUBLIC; 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Return current error string, or NULL if there was no error. 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char* crazy_context_get_error(crazy_context_t* context) _CRAZY_PUBLIC; 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Clear error in a given context. 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_clear_error(crazy_context_t* context) _CRAZY_PUBLIC; 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Set the explicit load address in a context object. Value 0 means 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the address is randomized. 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_load_address(crazy_context_t* context, 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t load_address) _CRAZY_PUBLIC; 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Return the current load address in a context. 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)size_t crazy_context_get_load_address(crazy_context_t* context) _CRAZY_PUBLIC; 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Set the explicit file offset in a context object. The value should 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// always page-aligned, or the load will fail. 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Note you can not use the same file with multiple offsets. See crbug/388223. 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_file_offset(crazy_context_t* context, 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t file_offset) _CRAZY_PUBLIC; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Return the current file offset in a context object. 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)size_t crazy_context_get_file_offset(crazy_context_t* context); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Add one or more paths to the list of library search paths held 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// by a given context. |path| is a string using a column (:) as a 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// list separator. As with the PATH variable, an empty list item 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// is equivalent to '.', the current directory. 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This can fail if too many paths are added to the context. 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NOTE: Calling this function appends new paths to the search list, 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// but all paths added with this function will be searched before 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the ones listed in LD_LIBRARY_PATH. 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_context_add_search_path( 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_context_t* context, 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* file_path) _CRAZY_PUBLIC; 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Find the ELF binary that contains |address|, and add its directory 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// path to the context's list of search directories. This is useful to 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// load libraries in the same directory than the current program itself. 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_context_add_search_path_for_address( 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_context_t* context, 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* address) _CRAZY_PUBLIC; 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Reset the search paths to the value of the LD_LIBRARY_PATH 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// environment variable. This essentially removes any paths 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// that were added with crazy_context_add_search_path() or 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// crazy_context_add_search_path_for_address(). 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_reset_search_paths(crazy_context_t* context) _CRAZY_PUBLIC; 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Record the value of |java_vm| inside of |context|. If this is not NULL, 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// which is the default, then after loading any library, the crazy linker 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// will look for a "JNI_OnLoad" symbol within it, and, if it exists, will call 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// it, passing the value of |java_vm| to it. If the function returns with 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// a jni version number that is smaller than |minimum_jni_version|, then 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the library load will fail with an error. 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The |java_vm| field is also saved in the crazy_library_t object, and 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// used at unload time to call JNI_OnUnload() if it exists. 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_java_vm(crazy_context_t* context, 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* java_vm, 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int minimum_jni_version); 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Retrieves the last values set with crazy_context_set_java_vm(). 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A value of NUMM in |*java_vm| means the feature is disabled. 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_get_java_vm(crazy_context_t* context, 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void** java_vm, 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int* minimum_jni_version); 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Destroy a given context object. 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_destroy(crazy_context_t* context) _CRAZY_PUBLIC; 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Some operations performed by the crazy linker might conflict with the 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// system linker if they are used concurrently in different threads 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// (e.g. modifying the list of shared libraries seen by GDB). To work 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// around this, the crazy linker provides a way to delay these conflicting 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// operations for a later time. 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This works by wrapping each of these operations in a small data structure 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// (crazy_callback_t), which can later be passed to crazy_callback_run() 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to execute it. 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The user must provide a function to record these callbacks during 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// library loading, by calling crazy_linker_set_callback_poster(). 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Once all libraries are loaded, the callbacks can be later called either 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// in a different thread, or when it is safe to assume the system linker 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// cannot be running in parallel. 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Callback handler. 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef void (*crazy_callback_handler_t)(void* opaque); 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A small structure used to model a callback provided by the crazy linker. 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use crazy_callback_run() to run the callback. 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef struct { 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_callback_handler_t handler; 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* opaque; 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} crazy_callback_t; 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Function to call to enable a callback into the crazy linker when delayed 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// operations are enabled (see crazy_context_set_callback_poster). A call 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to crazy_callback_poster_t returns true if the callback was successfully 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// set up and will occur later, false if callback could not be set up (and 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// so will never occur). 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef bool (*crazy_callback_poster_t)( 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_callback_t* callback, void* poster_opaque); 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Enable delayed operation, by passing the address of a 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |crazy_callback_poster_t| function, that will be called during library 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// loading to let the user record callbacks for delayed operations. 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Callers must copy the |crazy_callback_t| passed to |poster|. 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |poster_opaque| is an opaque value for client code use, passed back 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// on each call to |poster|. 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |poster| can be NULL to disable the feature. 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_set_callback_poster(crazy_context_t* context, 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_callback_poster_t poster, 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* poster_opaque); 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Return the address of the function that the crazy linker can use to 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// request callbacks, and the |poster_opaque| passed back on each call 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to |poster|. |poster| is NULL if the feature is disabled. 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_context_get_callback_poster(crazy_context_t* context, 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_callback_poster_t* poster, 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void** poster_opaque); 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Run a given |callback| in the current thread. Must only be called once 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// per callback. 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_callback_run(crazy_callback_t* callback); 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Opaque handle to a library as seen/loaded by the crazy linker. 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef struct crazy_library_t crazy_library_t; 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Try to open or load a library with the crazy linker. 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |lib_name| if the library name or path. If it contains a directory 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// separator (/), this is treated as a explicit file path, otherwise 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// it is treated as a base name, and the context's search path list 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// will be used to locate the corresponding file. 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |context| is a linker context handle. Can be NULL for defaults. 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// On success, return CRAZY_STATUS_SUCCESS and sets |*library|. 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Libraries are reference-counted, trying to open the same library 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// twice will return the same library handle. 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NOTE: The load address and file offset from the context only apply 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to the library being loaded (when not already in the process). If the 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// operations needs to load any dependency libraries, these will use 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// offset and address values of 0 to do so. 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NOTE: It is possible to open NDK system libraries (e.g. "liblog.so") 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// with this function, but they will be loaded with the system dlopen(). 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_open(crazy_library_t** library, 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* lib_name, 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_context_t* context) _CRAZY_PUBLIC; 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Try to open or load a library with the crazy linker. The 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// library is in a zip file with the name |zipfile_name|. Within the zip 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// file the library must be uncompressed and page aligned. |zipfile_name| 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// should be an absolute path name and |lib_name| should be a relative 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// pathname. The library in the zip file is expected to have the name 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// lib/<abi_tag>/crazy.<lib_name> where abi_tag is the abi directory matching 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// the ABI for which the crazy linker was compiled. Note this does not support 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// opening multiple libraries in the same zipfile, see crbug/388223. 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 _CRAZY_PUBLIC; 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A structure used to hold information about a given library. 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |load_address| is the library's actual (page-aligned) load address. 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |load_size| is the library's actual (page-aligned) size. 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |relro_start| is the address of the library's RELRO section in memory. 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |relso_size| is the size of the library's RELRO section (or 0 if none). 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |relro_fd| is the ashmem file descriptor for the shared section, if one 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// was created with crazy_library_enable_relro_sharing(), -1 otherwise. 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef struct { 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t load_address; 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t load_size; 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_start; 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_size; 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} crazy_library_info_t; 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Retrieve information about a given library. 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |library| is a library handle. 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |context| will get an error message on failure. 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// On success, return true and sets |*info|. 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Note that this function will fail for system libraries. 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_get_info(crazy_library_t* library, 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_context_t* context, 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_library_info_t* info); 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Checks whether the system can support RELRO section sharing. This is 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// mainly due to the fact that old Android kernel images have a bug in their 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// implementation of Ashmem region mapping protection. 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// If this function returns CRAZY_STATUS_FAILURE, then calls to 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// crazy_library_enable_relro_sharing() will return a failure to prevent 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the exploitation of this security issue in your code. 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_system_can_share_relro(void); 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Create an ashmem region containing a copy of the RELRO section for a given 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |library|. This can be used with crazy_library_use_shared_relro(). 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |load_address| can be specified as non-0 to ensure that the content of the 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// ashmem region corresponds to a RELRO relocated for a new load address. 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// on success, return CRAZY_STATUS_SUCCESS and sets |*relro_start| to the 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// start of the RELRO section in memory, |*relro_size| to its size in bytes 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// and |*relro_fd| to a file descriptor to a read-only ashmem region containing 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the data. On failure, return false and set error message in |context|. 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NOTE: On success, the caller becomes the owner of |*relro_fd| and is shall 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// close it appropriately. 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_create_shared_relro(crazy_library_t* library, 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_context_t* context, 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t load_address, 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t* relro_start, 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t* relro_size, 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int* relro_fd) _CRAZY_PUBLIC; 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use the shared RELRO section of the same library loaded in a different 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// address space. On success, return CRAZY_STATUS_SUCCESS and owns |relro_fd|. 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// On failure, return CRAZY_STATUS_FAILURE and sets error message in |context|. 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |library| is the library handle. 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |relro_start| is the address of the RELRO section in memory. 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |relro_size| is the size of the RELRO section. 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |relro_fd| is the file descriptor for the shared RELRO ashmem region. 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |context| will receive an error in case of failure. 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NOTE: This will fail if this is a system library, or if the RELRO 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// parameters do not match the library's actual load address. 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NOTE: The caller is responsible for closing the file descriptor after this 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// call. 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_use_shared_relro(crazy_library_t* library, 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_context_t* context, 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_start, 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_size, 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int relro_fd) _CRAZY_PUBLIC; 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Look for a library named |library_name| in the set of currently 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// loaded libraries, and return a handle for it in |*library| on success. 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Note that this increments the reference count on the library, thus 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the caller shall call crazy_library_close() when it's done with it. 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_find_by_name(const char* library_name, 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_library_t** library); 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Find the library that contains a given |address| in memory. 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// On success, return CRAZY_STATUS_SUCCESS and sets |*library|. 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_linker_find_library_from_address( 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* address, 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_library_t** library) _CRAZY_PUBLIC; 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Lookup a symbol's address by its |symbol_name| in a given library. 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This only looks at the symbols in |library|. 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// On success, returns CRAZY_STATUS_SUCCESS and sets |*symbol_address|, 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// which could be NULL for some symbols. 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_find_symbol(crazy_library_t* library, 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* symbol_name, 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void** symbol_address) _CRAZY_PUBLIC; 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Lookup a symbol's address in all libraries known by the crazy linker. 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |symbol_name| is the symbol name. On success, returns CRAZY_STATUS_SUCCESS 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// and sets |*symbol_address|. 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// NOTE: This will _not_ look into system libraries that were not opened 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// with the crazy linker. 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_linker_find_symbol(const char* symbol_name, 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void** symbol_address) _CRAZY_PUBLIC; 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Find the in-process library that contains a given memory address. 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Note that this works even if the memory is inside a system library that 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// was not previously opened with crazy_library_open(). 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |address| is the memory address. 331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// On success, returns CRAZY_STATUS_SUCCESS and sets |*library|. 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The caller muyst call crazy_library_close() once it's done with the 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// library. 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)crazy_status_t crazy_library_find_from_address( 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* address, 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_library_t** library) _CRAZY_PUBLIC; 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Close a library. This decrements its reference count. If it reaches 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// zero, the library be unloaded from the process. 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_library_close(crazy_library_t* library) _CRAZY_PUBLIC; 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Close a library, with associated context to support delayed operations. 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void crazy_library_close_with_context(crazy_library_t* library, 344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_context_t* context) _CRAZY_PUBLIC; 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __cplusplus 347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} /* extern "C" */ 348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif /* CRAZY_LINKER_H */ 351