Merge "NativeBridge: add "linked namespace" semantic corresponding to linker" am: 1238292db5 am: 21c8a291c5
am: 48e0e59c25
Change-Id: I5e126a5b78a0c360a9131ff9253918443d83544d
diff --git a/include/nativebridge/native_bridge.h b/include/nativebridge/native_bridge.h
index 45266de..929b8ae 100644
--- a/include/nativebridge/native_bridge.h
+++ b/include/nativebridge/native_bridge.h
@@ -116,14 +116,25 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 83f35b1..050373a 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -573,11 +573,11 @@
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 @@
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)) {
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk
index 4c3e862..c9468f0 100644
--- a/libnativebridge/tests/Android.mk
+++ b/libnativebridge/tests/Android.mk
@@ -24,7 +24,7 @@
NativeBridge3UnloadLibrary_test.cpp \
NativeBridge3GetError_test.cpp \
NativeBridge3IsPathSupported_test.cpp \
- NativeBridge3InitNamespace_test.cpp \
+ NativeBridge3InitAnonymousNamespace_test.cpp \
NativeBridge3CreateNamespace_test.cpp \
NativeBridge3LoadLibraryExt_test.cpp
diff --git a/libnativebridge/tests/DummyNativeBridge3.cpp b/libnativebridge/tests/DummyNativeBridge3.cpp
index 13fce85..4ef1c82 100644
--- a/libnativebridge/tests/DummyNativeBridge3.cpp
+++ b/libnativebridge/tests/DummyNativeBridge3.cpp
@@ -76,8 +76,8 @@
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 @@
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};
diff --git a/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
new file mode 100644
index 0000000..b0d6b09
--- /dev/null
+++ b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "NativeBridgeTest.h"
+
+namespace android {
+
+constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
+
+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, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));
+
+ // Clean-up code_cache
+ ASSERT_EQ(0, rmdir(kCodeCache));
+}
+
+} // namespace android
diff --git a/libnativebridge/tests/NativeBridge3InitNamespace_test.cpp b/libnativebridge/tests/NativeBridge3InitNamespace_test.cpp
deleted file mode 100644
index ae0fd2b..0000000
--- a/libnativebridge/tests/NativeBridge3InitNamespace_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#include "NativeBridgeTest.h"
-
-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());
-
- ASSERT_EQ(3U, NativeBridgeGetVersion());
- ASSERT_EQ(true, NativeBridgeInitNamespace(nullptr, nullptr));
-
- // Clean-up code_cache
- ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-} // namespace android
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 74f2f1d..f3391d1 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -183,6 +183,11 @@
return false;
}
+ if (!NativeBridgeLinkNamespaces(ns, nullptr, public_libraries_.c_str())) {
+ *error_msg = NativeBridgeGetError();
+ return false;
+ }
+
native_loader_ns = NativeLoaderNamespace(ns);
}
@@ -324,8 +329,8 @@
// 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();
}