summaryrefslogtreecommitdiffstats
path: root/include/nativebridge/native_bridge.h
blob: 929b8aec47bab908170b905ba1a338cc135c07fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef NATIVE_BRIDGE_H_
#define NATIVE_BRIDGE_H_

#include "jni.h"
#include <signal.h>
#include <stdint.h>
#include <sys/types.h>

namespace android {

struct NativeBridgeRuntimeCallbacks;
struct NativeBridgeRuntimeValues;

// Function pointer type for sigaction. This is mostly the signature of a signal handler, except
// for the return type. The runtime needs to know whether the signal was handled or should be given
// to the chain.
typedef bool (*NativeBridgeSignalHandlerFn)(int, siginfo_t*, void*);


// Open the native bridge, if any. Should be called by Runtime::Init(). A null library filename
// signals that we do not want to load a native bridge.
bool LoadNativeBridge(const char* native_bridge_library_filename,
                      const NativeBridgeRuntimeCallbacks* runtime_callbacks);

// Quick check whether a native bridge will be needed. This is based off of the instruction set
// of the process.
bool NeedsNativeBridge(const char* instruction_set);

// Do the early initialization part of the native bridge, if necessary. This should be done under
// high privileges.
bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set);

// Initialize the native bridge, if any. Should be called by Runtime::DidForkFromZygote. The JNIEnv*
// will be used to modify the app environment for the bridge.
bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set);

// Unload the native bridge, if any. Should be called by Runtime::DidForkFromZygote.
void UnloadNativeBridge();

// Check whether a native bridge is available (opened or initialized). Requires a prior call to
// LoadNativeBridge.
bool NativeBridgeAvailable();

// Check whether a native bridge is available (initialized). Requires a prior call to
// LoadNativeBridge & InitializeNativeBridge.
bool NativeBridgeInitialized();

// Load a shared library that is supported by the native bridge.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeLoadLibraryExt() instead in namespace scenario.
void* NativeBridgeLoadLibrary(const char* libpath, int flag);

// Get a native bridge trampoline for specified native method.
void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len);

// True if native library paths are valid and is for an ABI that is supported by native bridge.
// The *libpath* must point to a library.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeIsPathSupported() instead in namespace scenario.
bool NativeBridgeIsSupported(const char* libpath);

// Returns the version number of the native bridge. This information is available after a
// successful LoadNativeBridge() and before closing it, that is, as long as NativeBridgeAvailable()
// returns true. Returns 0 otherwise.
uint32_t NativeBridgeGetVersion();

// Returns a signal handler that the bridge would like to be managed. Only valid for a native
// bridge supporting the version 2 interface. Will return null if the bridge does not support
// version 2, or if it doesn't have a signal handler it wants to be known.
NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal);

// Returns whether we have seen a native bridge error. This could happen because the library
// was not found, rejected, could not be initialized and so on.
//
// This functionality is mainly for testing.
bool NativeBridgeError();

// Returns whether a given string is acceptable as a native bridge library filename.
//
// This functionality is exposed mainly for testing.
bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename);

// Decrements the reference count on the dynamic library handler. If the reference count drops
// to zero then the dynamic library is unloaded.
int NativeBridgeUnloadLibrary(void* handle);

// Get last error message of native bridge when fail to load library or search symbol.
// This is reflection of dlerror() for native bridge.
const char* NativeBridgeGetError();

struct native_bridge_namespace_t;

// True if native library paths are valid and is for an ABI that is supported by native bridge.
// Different from NativeBridgeIsSupported(), the *path* here must be a directory containing
// libraries of an ABI.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeIsSupported() instead in non-namespace scenario.
bool NativeBridgeIsPathSupported(const char* path);

// Initializes anonymous namespace.
// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
//
// The anonymous namespace is used in the case when a NativeBridge implementation
// cannot identify the caller of dlopen/dlsym which happens for the code not loaded
// by dynamic linker; for example calls from the mono-compiled code.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
                                        const char* anon_ns_library_path);

// Create new namespace in which native libraries will be loaded.
// NativeBridge's peer of android_create_namespace() of dynamic linker.
//
// The libraries in the namespace are searched by folowing order:
// 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
// 2. In directories specified by DT_RUNPATH of the "needed by" binary.
// 3. deault_library_path (This of this as namespace-local default library path)
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
                                                       const char* ld_library_path,
                                                       const char* default_library_path,
                                                       uint64_t type,
                                                       const char* permitted_when_isolated_path,
                                                       native_bridge_namespace_t* parent_ns);

// Creates a link which shares some libraries from one namespace to another.
// NativeBridge's peer of android_link_namespaces() of dynamic linker.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
                                const char* shared_libs_sonames);

// Load a shared library with namespace key that is supported by the native bridge.
// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
// extension.
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns);

// Native bridge interfaces to runtime.
struct NativeBridgeCallbacks {
  // Version number of the interface.
  uint32_t version;

  // Initialize native bridge. Native bridge's internal implementation must ensure MT safety and
  // that the native bridge is initialized only once. Thus it is OK to call this interface for an
  // already initialized native bridge.
  //
  // Parameters:
  //   runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
  // Returns:
  //   true if initialization was successful.
  bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
                     const char* instruction_set);

  // Load a shared library that is supported by the native bridge.
  //
  // Parameters:
  //   libpath [IN] path to the shared library
  //   flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
  // Returns:
  //   The opaque handle of the shared library if sucessful, otherwise NULL
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Use loadLibraryExt instead in namespace scenario.
  void* (*loadLibrary)(const char* libpath, int flag);

  // Get a native bridge trampoline for specified native method. The trampoline has same
  // sigature as the native method.
  //
  // Parameters:
  //   handle [IN] the handle returned from loadLibrary
  //   shorty [IN] short descriptor of native method
  //   len [IN] length of shorty
  // Returns:
  //   address of trampoline if successful, otherwise NULL
  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);

  // Check whether native library is valid and is for an ABI that is supported by native bridge.
  //
  // Parameters:
  //   libpath [IN] path to the shared library
  // Returns:
  //   TRUE if library is supported by native bridge, FALSE otherwise
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Use isPathSupported instead in namespace scenario.
  bool (*isSupported)(const char* libpath);

  // Provide environment values required by the app running with native bridge according to the
  // instruction set.
  //
  // Parameters:
  //   instruction_set [IN] the instruction set of the app
  // Returns:
  //   NULL if not supported by native bridge.
  //   Otherwise, return all environment values to be set after fork.
  const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);

  // Added callbacks in version 2.

  // Check whether the bridge is compatible with the given version. A bridge may decide not to be
  // forwards- or backwards-compatible, and libnativebridge will then stop using it.
  //
  // Parameters:
  //   bridge_version [IN] the version of libnativebridge.
  // Returns:
  //   true if the native bridge supports the given version of libnativebridge.
  bool (*isCompatibleWith)(uint32_t bridge_version);

  // A callback to retrieve a native bridge's signal handler for the specified signal. The runtime
  // will ensure that the signal handler is being called after the runtime's own handler, but before
  // all chained handlers. The native bridge should not try to install the handler by itself, as
  // that will potentially lead to cycles.
  //
  // Parameters:
  //   signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is
  //                 supported by the runtime.
  // Returns:
  //   NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the
  //   runtime.
  //   Otherwise, a pointer to the signal handler.
  NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal);

  // Added callbacks in version 3.

  // Decrements the reference count on the dynamic library handler. If the reference count drops
  // to zero then the dynamic library is unloaded.
  //
  // Parameters:
  //   handle [IN] the handler of a dynamic library.
  //
  // Returns:
  //   0 on success, and nonzero on error.
  int (*unloadLibrary)(void* handle);

  // Dump the last failure message of native bridge when fail to load library or search symbol.
  //
  // Parameters:
  //
  // Returns:
  //   A string describing the most recent error that occurred when load library
  //   or lookup symbol via native bridge.
  const char* (*getError)();

  // Check whether library paths are supported by native bridge.
  //
  // Parameters:
  //   library_path [IN] search paths for native libraries (directories separated by ':')
  // Returns:
  //   TRUE if libraries within search paths are supported by native bridge, FALSE otherwise
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Use isSupported instead in non-namespace scenario.
  bool (*isPathSupported)(const char* library_path);

  // Initializes anonymous namespace at native bridge side.
  // NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
  //
  // The anonymous namespace is used in the case when a NativeBridge implementation
  // cannot identify the caller of dlopen/dlsym which happens for the code not loaded
  // by dynamic linker; for example calls from the mono-compiled code.
  //
  // Parameters:
  //   public_ns_sonames [IN] the name of "public" libraries.
  //   anon_ns_library_path [IN] the library search path of (anonymous) namespace.
  // Returns:
  //   true if the pass is ok.
  //   Otherwise, false.
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Should not use in non-namespace scenario.
  bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);

  // Create new namespace in which native libraries will be loaded.
  // NativeBridge's peer of android_create_namespace() of dynamic linker.
  //
  // Parameters:
  //   name [IN] the name of the namespace.
  //   ld_library_path [IN] the first set of library search paths of the namespace.
  //   default_library_path [IN] the second set of library search path of the namespace.
  //   type [IN] the attribute of the namespace.
  //   permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is).
  //   parent_ns [IN] the pointer of the parent namespace to be inherited from.
  // Returns:
  //   native_bridge_namespace_t* for created namespace or nullptr in the case of error.
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Should not use in non-namespace scenario.
  native_bridge_namespace_t* (*createNamespace)(const char* name,
                                                const char* ld_library_path,
                                                const char* default_library_path,
                                                uint64_t type,
                                                const char* permitted_when_isolated_path,
                                                native_bridge_namespace_t* parent_ns);

  // Creates a link which shares some libraries from one namespace to another.
  // NativeBridge's peer of android_link_namespaces() of dynamic linker.
  //
  // Parameters:
  //   from [IN] the namespace where libraries are accessed.
  //   to [IN] the namespace where libraries are loaded.
  //   shared_libs_sonames [IN] the libraries to be shared.
  //
  // Returns:
  //   Whether successed or not.
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Should not use in non-namespace scenario.
  bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
                         const char* shared_libs_sonames);

  // Load a shared library within a namespace.
  // NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
  // extension.
  //
  // Parameters:
  //   libpath [IN] path to the shared library
  //   flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
  //   ns [IN] the pointer of the namespace in which the library should be loaded.
  // Returns:
  //   The opaque handle of the shared library if sucessful, otherwise NULL
  //
  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
  // Use loadLibrary instead in non-namespace scenario.
  void* (*loadLibraryExt)(const char* libpath, int flag, native_bridge_namespace_t* ns);
};

// Runtime interfaces to native bridge.
struct NativeBridgeRuntimeCallbacks {
  // Get shorty of a Java method. The shorty is supposed to be persistent in memory.
  //
  // Parameters:
  //   env [IN] pointer to JNIenv.
  //   mid [IN] Java methodID.
  // Returns:
  //   short descriptor for method.
  const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);

  // Get number of native methods for specified class.
  //
  // Parameters:
  //   env [IN] pointer to JNIenv.
  //   clazz [IN] Java class object.
  // Returns:
  //   number of native methods.
  uint32_t (*getNativeMethodCount)(JNIEnv* env, jclass clazz);

  // Get at most 'method_count' native methods for specified class 'clazz'. Results are outputed
  // via 'methods' [OUT]. The signature pointer in JNINativeMethod is reused as the method shorty.
  //
  // Parameters:
  //   env [IN] pointer to JNIenv.
  //   clazz [IN] Java class object.
  //   methods [OUT] array of method with the name, shorty, and fnPtr.
  //   method_count [IN] max number of elements in methods.
  // Returns:
  //   number of method it actually wrote to methods.
  uint32_t (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
                               uint32_t method_count);
};

};  // namespace android

#endif  // NATIVE_BRIDGE_H_