OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 #ifndef CRAZY_LINKER_H |
| 5 #define CRAZY_LINKER_H |
| 6 |
| 7 // This is the crazy linker, a custom dynamic linker that can be used |
| 8 // by NDK applications to load shared libraries (not executables) with |
| 9 // a twist. |
| 10 // |
| 11 // Compared to the dynamic linker, the crazy one has the following |
| 12 // features: |
| 13 // |
| 14 // - It can use an arbitrary search path. |
| 15 // |
| 16 // - It can load a library at a memory fixed address. |
| 17 // |
| 18 // - It can share the RELRO section between two libraries |
| 19 // loaded at the same address in two distinct processes. |
| 20 // |
| 21 #include <dlfcn.h> |
| 22 #include <stddef.h> |
| 23 |
| 24 #ifdef __cplusplus |
| 25 extern "C" { |
| 26 #endif |
| 27 |
| 28 // Function attribute to indicate that it needs to be exported by |
| 29 // the library. |
| 30 #define _CRAZY_PUBLIC __attribute__((__visibility__("default"))) |
| 31 |
| 32 // Status values returned by crazy linker functions to indicate |
| 33 // success or failure. They were chosen to match boolean values, |
| 34 // this allows one to test for failures with: |
| 35 // |
| 36 // if (!crazy_linker_function(....)) { |
| 37 // ... an error occured. |
| 38 // } |
| 39 // |
| 40 // If the function called used a crazy_context_t, it is possible to |
| 41 // retrieve the error details with crazy_context_get_error(). |
| 42 typedef enum { |
| 43 CRAZY_STATUS_KO = 0, |
| 44 CRAZY_STATUS_OK = 1 |
| 45 } crazy_status_t; |
| 46 |
| 47 // Opaque handle to a context object that will hold parameters |
| 48 // for the crazy linker's operations. For example, this is where |
| 49 // you would set the explicit load address, and other user-provided |
| 50 // values before calling functions like crazy_linker_load(). |
| 51 // |
| 52 // The context holds a list of library search paths, initialized to |
| 53 // the content of the LD_LIBRARY_PATH variable on creation. |
| 54 // |
| 55 // The context also holds a string buffer to hold error messages that |
| 56 // can be queried with crazy_context_get_error(). |
| 57 typedef struct crazy_context_t crazy_context_t; |
| 58 |
| 59 // Create a new context object. |
| 60 crazy_context_t* crazy_context_create(void) _CRAZY_PUBLIC; |
| 61 |
| 62 // Return current error string, or NULL if there was no error. |
| 63 const char* crazy_context_get_error(crazy_context_t* context) |
| 64 _CRAZY_PUBLIC; |
| 65 |
| 66 // Clear error in a given context. |
| 67 void crazy_context_clear_error(crazy_context_t* context) |
| 68 _CRAZY_PUBLIC; |
| 69 |
| 70 // Set the explicit load address in a context object. Value 0 means |
| 71 // the address is randomized. |
| 72 void crazy_context_set_load_address(crazy_context_t* context, |
| 73 size_t load_address) _CRAZY_PUBLIC; |
| 74 |
| 75 // Return the current load address in a context. |
| 76 size_t crazy_context_get_load_address(crazy_context_t* context) |
| 77 _CRAZY_PUBLIC; |
| 78 |
| 79 // Set the explicit file offset in a context object. The value should |
| 80 // always page-aligned, or the load will fail. |
| 81 void crazy_context_set_file_offset(crazy_context_t* context, |
| 82 size_t file_offset) _CRAZY_PUBLIC; |
| 83 |
| 84 // Return the current file offset in a context object. |
| 85 size_t crazy_context_get_file_offset(crazy_context_t* context); |
| 86 |
| 87 // Add one or more paths to the list of library search paths held |
| 88 // by a given context. |path| is a string using a column (:) as a |
| 89 // list separator. As with the PATH variable, an empty list item |
| 90 // is equivalent to '.', the current directory. |
| 91 // This can fail if too many paths are added to the context. |
| 92 crazy_status_t crazy_context_add_search_path(crazy_context_t* context, |
| 93 const char* file_path) |
| 94 _CRAZY_PUBLIC; |
| 95 |
| 96 // Find the ELF binary that contains |address|, and add its directory |
| 97 // path to the context's list of search directories. This is useful to |
| 98 // load libraries in the same directory than the current program itself. |
| 99 crazy_status_t crazy_context_add_search_path_for_address( |
| 100 crazy_context_t* context, |
| 101 void* address) _CRAZY_PUBLIC; |
| 102 |
| 103 // Reset the search paths to the value of the LD_LIBRARY_PATH |
| 104 // environment variable. |
| 105 void crazy_context_reset_search_paths(crazy_context_t* context) |
| 106 _CRAZY_PUBLIC; |
| 107 |
| 108 // Destroy a given context object. |
| 109 void crazy_context_destroy(crazy_context_t* context) _CRAZY_PUBLIC; |
| 110 |
| 111 // Opaque handle to a library as seen/loaded by the crazy linker. |
| 112 typedef struct crazy_library_t crazy_library_t; |
| 113 |
| 114 // Try to open or load a library with the crazy linker. |
| 115 // |lib_name| if the library name or path. If it contains a directory |
| 116 // separator (/), this is treated as a explicit file path, otherwise |
| 117 // it is treated as a base name, and the context's search path list |
| 118 // will be used to locate the corresponding file. |
| 119 // |context| is a linker context handle. Can be NULL for defaults. |
| 120 // On success, return CRAZY_STATUS_OK and sets |*library|. |
| 121 // Libraries are reference-counted, trying to open the same library |
| 122 // twice will return the same library handle. |
| 123 // |
| 124 // NOTE: The load address and file offset from the context only apply |
| 125 // to the library being loaded (when not already in the process). If the |
| 126 // operations needs to load any dependency libraries, these will use |
| 127 // offset and address values of 0 to do so. |
| 128 // |
| 129 // NOTE: It is possible to open system libraries (e.g. "libc.so") |
| 130 // with this function. If the library is already in the process, |
| 131 // a proper crazy_library_t handle will be returned for it. If the |
| 132 // system library is not loaded yet, it will be loaded through |
| 133 // dlopen() instead of the crazy linker. |
| 134 crazy_status_t crazy_library_open(crazy_library_t** library, |
| 135 const char* lib_name, |
| 136 crazy_context_t* context) |
| 137 _CRAZY_PUBLIC; |
| 138 |
| 139 // A structure used to hold information about a given library. |
| 140 // |load_address| is the library's actual (page-aligned) load address. |
| 141 // |load_size| is the library's actual (page-aligned) size. |
| 142 // |relro_start| is the address of the library's RELRO section in memory. |
| 143 // |relso_size| is the size of the library's RELRO section (or 0 if none). |
| 144 // |relro_fd| is the ashmem file descriptor for the shared section, or -1. |
| 145 typedef struct { |
| 146 size_t load_address; |
| 147 size_t load_size; |
| 148 size_t relro_start; |
| 149 size_t relro_size; |
| 150 int relro_fd; |
| 151 } crazy_library_info_t; |
| 152 |
| 153 // Retrieve information about a given library. |
| 154 // |library| is a library handle. |
| 155 // |context| will get an error message on failure. |
| 156 // On success, return true and sets |*info|. |
| 157 // Note that this function will fail for system libraries. |
| 158 crazy_status_t crazy_library_get_info(crazy_library_t* library, |
| 159 crazy_context_t* context, |
| 160 crazy_library_info_t* info); |
| 161 |
| 162 |
| 163 // Enable RELRO section sharing for this library. This can only be |
| 164 // called once per library loaded through crazy_library_open(), and |
| 165 // will only work for non-system libraries. |
| 166 // On success, return CRAZY_STATUS_OK and sets |*library_info| with |
| 167 // all relevant data. On failure, return CRAZY_STATUS_KO and sets |
| 168 // the error message in |context|. |
| 169 crazy_status_t crazy_library_enable_relro_sharing( |
| 170 crazy_library_t* library, |
| 171 crazy_context_t* context) _CRAZY_PUBLIC; |
| 172 |
| 173 // Use the shared RELRO section of the same library loaded in a different |
| 174 // address space. On success, return CRAZY_STATUS_OK and owns |relro_fd|. |
| 175 // On failure, return CRAZY_STATUS_KO and sets error message in |context|. |
| 176 // |library| is the library handle. |
| 177 // |relro_start| is the address of the RELRO section in memory. |
| 178 // |relro_size| is the size of the RELRO section. |
| 179 // |relro_fd| is the file descriptor for the shared RELRO ashmem region. |
| 180 // |context| will receive an error in case of failure. |
| 181 // NOTE: This will fail if this is a system library, or if the RELRO |
| 182 // parameters do not match the library's actual load address. |
| 183 crazy_status_t crazy_library_use_relro_sharing( |
| 184 crazy_library_t* library, |
| 185 size_t relro_start, |
| 186 size_t relro_size, |
| 187 int relro_fd, |
| 188 crazy_context_t* context) _CRAZY_PUBLIC; |
| 189 |
| 190 // Look for a library named |library_name| in the set of currently |
| 191 // loaded libraries, and return a handle for it in |*library| on success. |
| 192 // Note that this increments the reference count on the library, thus |
| 193 // the caller shall call crazy_library_close() when it's done with it. |
| 194 crazy_status_t crazy_library_find_by_name(const char* library_name, |
| 195 crazy_library_t** library); |
| 196 |
| 197 // Find the library that contains a given |address| in memory. |
| 198 // On success, return CRAZY_STATUS_OK and sets |*library|. |
| 199 crazy_status_t crazy_linker_find_library_from_address( |
| 200 void* address, crazy_library_t** library) _CRAZY_PUBLIC; |
| 201 |
| 202 // Lookup a symbol's address by its |symbol_name| in a given library. |
| 203 // This only looks at the symbols in |library|. |
| 204 // On success, returns CRAZY_STATUS_OK and sets |*symbol_address|, |
| 205 // which could be NULL for some symbols. |
| 206 crazy_status_t crazy_library_find_symbol( |
| 207 crazy_library_t* library, |
| 208 const char* symbol_name, |
| 209 void** symbol_address) _CRAZY_PUBLIC; |
| 210 |
| 211 // Lookup a symbol's address in all libraries known by the crazy linker. |
| 212 // |symbol_name| is the symbol name. On success, returns CRAZY_STATUS_OK |
| 213 // and sets |*symbol_address|. |
| 214 // NOTE: This will _not_ look into system libraries that were not opened |
| 215 // with the crazy linker. |
| 216 crazy_status_t crazy_linker_find_symbol( |
| 217 const char* symbol_name, |
| 218 void** symbol_address) _CRAZY_PUBLIC; |
| 219 |
| 220 // Find the in-process library that contains a given memory address. |
| 221 // Note that this works even if the memory is inside a system library that |
| 222 // was not previously opened with crazy_library_open(). |
| 223 // |address| is the memory address. |
| 224 // On success, returns CRAZY_STATUS_OK and sets |*library|. |
| 225 // The caller muyst call crazy_library_close() once it's done with the |
| 226 // library. |
| 227 crazy_status_t crazy_library_find_from_address( |
| 228 void* address, crazy_library_t** library) _CRAZY_PUBLIC; |
| 229 |
| 230 // Close a library. This decrements its reference count. If it reaches |
| 231 // zero, the library be unloaded from the process. |
| 232 void crazy_library_close(crazy_library_t* library) _CRAZY_PUBLIC; |
| 233 |
| 234 #ifdef __cplusplus |
| 235 } /* extern "C" */ |
| 236 #endif |
| 237 |
| 238 #endif /* CRAZY_LINKER_H */ |
OLD | NEW |