Merge "NativeBridge: add "linked namespace" semantic corresponding to linker"
This commit is contained in:
commit
1238292db5
|
@ -116,14 +116,25 @@ struct native_bridge_namespace_t;
|
|||
// Use NativeBridgeIsSupported() instead in non-namespace scenario.
|
||||
bool NativeBridgeIsPathSupported(const char* path);
|
||||
|
||||
// Initializes public and anonymous namespace at native bridge side.
|
||||
// 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 NativeBridgeInitNamespace(const char* public_ns_sonames,
|
||||
const char* anon_ns_library_path);
|
||||
bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
|
||||
const char* anon_ns_library_path);
|
||||
|
||||
// Create a namespace and pass the key of related namespaces to native bridge.
|
||||
// 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.
|
||||
|
@ -134,7 +145,17 @@ native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
|
|||
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.
|
||||
|
@ -152,7 +173,7 @@ struct NativeBridgeCallbacks {
|
|||
// Parameters:
|
||||
// runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
|
||||
// Returns:
|
||||
// true iff initialization was successful.
|
||||
// true if initialization was successful.
|
||||
bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
|
||||
const char* instruction_set);
|
||||
|
||||
|
@ -194,10 +215,10 @@ struct NativeBridgeCallbacks {
|
|||
// instruction set.
|
||||
//
|
||||
// Parameters:
|
||||
// instruction_set [IN] the instruction set of the app
|
||||
// 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.
|
||||
// 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.
|
||||
|
@ -206,9 +227,9 @@ struct NativeBridgeCallbacks {
|
|||
// forwards- or backwards-compatible, and libnativebridge will then stop using it.
|
||||
//
|
||||
// Parameters:
|
||||
// bridge_version [IN] the version of libnativebridge.
|
||||
// bridge_version [IN] the version of libnativebridge.
|
||||
// Returns:
|
||||
// true iff the native bridge supports the given version of libnativebridge.
|
||||
// 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
|
||||
|
@ -217,12 +238,12 @@ struct NativeBridgeCallbacks {
|
|||
// that will potentially lead to cycles.
|
||||
//
|
||||
// Parameters:
|
||||
// signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is
|
||||
// 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.
|
||||
// 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.
|
||||
|
@ -231,7 +252,7 @@ struct NativeBridgeCallbacks {
|
|||
// to zero then the dynamic library is unloaded.
|
||||
//
|
||||
// Parameters:
|
||||
// handle [IN] the handler of a dynamic library.
|
||||
// handle [IN] the handler of a dynamic library.
|
||||
//
|
||||
// Returns:
|
||||
// 0 on success, and nonzero on error.
|
||||
|
@ -257,33 +278,36 @@ struct NativeBridgeCallbacks {
|
|||
// Use isSupported instead in non-namespace scenario.
|
||||
bool (*isPathSupported)(const char* library_path);
|
||||
|
||||
// Initializes anonymous namespace at native bridge side and pass the key of
|
||||
// two namespaces(default and anonymous) owned by dynamic linker to native bridge.
|
||||
// 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.
|
||||
// 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.
|
||||
// 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 (*initNamespace)(const char* public_ns_sonames,
|
||||
const char* anon_ns_library_path);
|
||||
bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);
|
||||
|
||||
|
||||
// Create a namespace and pass the key of releated namespaces to native bridge.
|
||||
// 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.
|
||||
// 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.
|
||||
// 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.
|
||||
|
@ -294,7 +318,25 @@ struct NativeBridgeCallbacks {
|
|||
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
|
||||
|
|
|
@ -573,11 +573,11 @@ bool NativeBridgeIsPathSupported(const char* path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NativeBridgeInitNamespace(const char* public_ns_sonames,
|
||||
const char* anon_ns_library_path) {
|
||||
bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
|
||||
const char* anon_ns_library_path) {
|
||||
if (NativeBridgeInitialized()) {
|
||||
if (isCompatibleWith(NAMESPACE_VERSION)) {
|
||||
return callbacks->initNamespace(public_ns_sonames, anon_ns_library_path);
|
||||
return callbacks->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path);
|
||||
} else {
|
||||
ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
|
||||
}
|
||||
|
@ -608,6 +608,19 @@ native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
|
||||
const char* shared_libs_sonames) {
|
||||
if (NativeBridgeInitialized()) {
|
||||
if (isCompatibleWith(NAMESPACE_VERSION)) {
|
||||
return callbacks->linkNamespaces(from, to, shared_libs_sonames);
|
||||
} else {
|
||||
ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
|
||||
if (NativeBridgeInitialized()) {
|
||||
if (isCompatibleWith(NAMESPACE_VERSION)) {
|
||||
|
|
|
@ -24,7 +24,7 @@ test_src_files := \
|
|||
NativeBridge3UnloadLibrary_test.cpp \
|
||||
NativeBridge3GetError_test.cpp \
|
||||
NativeBridge3IsPathSupported_test.cpp \
|
||||
NativeBridge3InitNamespace_test.cpp \
|
||||
NativeBridge3InitAnonymousNamespace_test.cpp \
|
||||
NativeBridge3CreateNamespace_test.cpp \
|
||||
NativeBridge3LoadLibraryExt_test.cpp
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@ extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
|
|||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool native_bridge3_initNamespace(const char* /* public_ns_sonames */,
|
||||
const char* /* anon_ns_library_path */) {
|
||||
extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
|
||||
const char* /* anon_ns_library_path */) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -91,30 +91,34 @@ native_bridge3_createNamespace(const char* /* name */,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
|
||||
android::native_bridge_namespace_t* /* to */,
|
||||
const char* /* shared_libs_soname */) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
|
||||
int /* flag */,
|
||||
android::native_bridge_namespace_t* /* ns */) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
android::NativeBridgeCallbacks NativeBridgeItf {
|
||||
// v1
|
||||
.version = 3,
|
||||
.initialize = &native_bridge3_initialize,
|
||||
.loadLibrary = &native_bridge3_loadLibrary,
|
||||
.getTrampoline = &native_bridge3_getTrampoline,
|
||||
.isSupported = &native_bridge3_isSupported,
|
||||
.getAppEnv = &native_bridge3_getAppEnv,
|
||||
// v2
|
||||
.isCompatibleWith = &native_bridge3_isCompatibleWith,
|
||||
.getSignalHandler = &native_bridge3_getSignalHandler,
|
||||
// v3
|
||||
.unloadLibrary = &native_bridge3_unloadLibrary,
|
||||
.getError = &native_bridge3_getError,
|
||||
.isPathSupported = &native_bridge3_isPathSupported,
|
||||
.initNamespace = &native_bridge3_initNamespace,
|
||||
.createNamespace = &native_bridge3_createNamespace,
|
||||
.loadLibraryExt = &native_bridge3_loadLibraryExt
|
||||
};
|
||||
|
||||
android::NativeBridgeCallbacks NativeBridgeItf{
|
||||
// v1
|
||||
.version = 3,
|
||||
.initialize = &native_bridge3_initialize,
|
||||
.loadLibrary = &native_bridge3_loadLibrary,
|
||||
.getTrampoline = &native_bridge3_getTrampoline,
|
||||
.isSupported = &native_bridge3_isSupported,
|
||||
.getAppEnv = &native_bridge3_getAppEnv,
|
||||
// v2
|
||||
.isCompatibleWith = &native_bridge3_isCompatibleWith,
|
||||
.getSignalHandler = &native_bridge3_getSignalHandler,
|
||||
// v3
|
||||
.unloadLibrary = &native_bridge3_unloadLibrary,
|
||||
.getError = &native_bridge3_getError,
|
||||
.isPathSupported = &native_bridge3_isPathSupported,
|
||||
.initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
|
||||
.createNamespace = &native_bridge3_createNamespace,
|
||||
.linkNamespaces = &native_bridge3_linkNamespaces,
|
||||
.loadLibraryExt = &native_bridge3_loadLibraryExt};
|
||||
|
|
|
@ -20,20 +20,20 @@ namespace android {
|
|||
|
||||
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
|
||||
|
||||
TEST_F(NativeBridgeTest, V3_InitNamespace) {
|
||||
// Init
|
||||
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
|
||||
ASSERT_TRUE(NativeBridgeAvailable());
|
||||
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
|
||||
ASSERT_TRUE(NativeBridgeAvailable());
|
||||
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
|
||||
ASSERT_TRUE(NativeBridgeAvailable());
|
||||
TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
|
||||
// Init
|
||||
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
|
||||
ASSERT_TRUE(NativeBridgeAvailable());
|
||||
ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
|
||||
ASSERT_TRUE(NativeBridgeAvailable());
|
||||
ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
|
||||
ASSERT_TRUE(NativeBridgeAvailable());
|
||||
|
||||
ASSERT_EQ(3U, NativeBridgeGetVersion());
|
||||
ASSERT_EQ(true, NativeBridgeInitNamespace(nullptr, nullptr));
|
||||
ASSERT_EQ(3U, NativeBridgeGetVersion());
|
||||
ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));
|
||||
|
||||
// Clean-up code_cache
|
||||
ASSERT_EQ(0, rmdir(kCodeCache));
|
||||
// Clean-up code_cache
|
||||
ASSERT_EQ(0, rmdir(kCodeCache));
|
||||
}
|
||||
|
||||
} // namespace android
|
|
@ -183,6 +183,11 @@ class LibraryNamespaces {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!NativeBridgeLinkNamespaces(ns, nullptr, public_libraries_.c_str())) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
return false;
|
||||
}
|
||||
|
||||
native_loader_ns = NativeLoaderNamespace(ns);
|
||||
}
|
||||
|
||||
|
@ -324,8 +329,8 @@ class LibraryNamespaces {
|
|||
|
||||
// and now initialize native bridge namespaces if necessary.
|
||||
if (NativeBridgeInitialized()) {
|
||||
initialized_ = NativeBridgeInitNamespace(public_libraries_.c_str(),
|
||||
is_native_bridge ? library_path : nullptr);
|
||||
initialized_ = NativeBridgeInitAnonymousNamespace(public_libraries_.c_str(),
|
||||
is_native_bridge ? library_path : nullptr);
|
||||
if (!initialized_) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue