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