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