Merge "NativeBridge: add "linked namespace" semantic corresponding to linker"

am: 1238292db5

Change-Id: I9200efa2d6c3f0d1b96b81e5c065f85f8b96b06f
This commit is contained in:
Zhenhua WANG 2017-04-07 21:54:57 +00:00 committed by android-build-merger
commit 21c8a291c5
6 changed files with 137 additions and 73 deletions

View file

@ -116,14 +116,25 @@ struct native_bridge_namespace_t;
// Use NativeBridgeIsSupported() instead in non-namespace scenario. // Use NativeBridgeIsSupported() instead in non-namespace scenario.
bool NativeBridgeIsPathSupported(const char* path); 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. // Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario. // Should not use in non-namespace scenario.
bool NativeBridgeInitNamespace(const char* public_ns_sonames, bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
const char* anon_ns_library_path); 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. // Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario. // 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, const char* permitted_when_isolated_path,
native_bridge_namespace_t* parent_ns); 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. // 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. // Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeLoadLibrary() instead in non-namespace scenario. // Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
@ -152,7 +173,7 @@ struct NativeBridgeCallbacks {
// Parameters: // Parameters:
// runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks. // runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
// Returns: // Returns:
// true iff initialization was successful. // true if initialization was successful.
bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir, bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
const char* instruction_set); const char* instruction_set);
@ -208,7 +229,7 @@ struct NativeBridgeCallbacks {
// Parameters: // Parameters:
// bridge_version [IN] the version of libnativebridge. // bridge_version [IN] the version of libnativebridge.
// Returns: // 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); bool (*isCompatibleWith)(uint32_t bridge_version);
// A callback to retrieve a native bridge's signal handler for the specified signal. The runtime // A callback to retrieve a native bridge's signal handler for the specified signal. The runtime
@ -257,8 +278,12 @@ struct NativeBridgeCallbacks {
// Use isSupported instead in non-namespace scenario. // Use isSupported instead in non-namespace scenario.
bool (*isPathSupported)(const char* library_path); bool (*isPathSupported)(const char* library_path);
// Initializes anonymous namespace at native bridge side and pass the key of // Initializes anonymous namespace at native bridge side.
// two namespaces(default and anonymous) owned by dynamic linker to native bridge. // 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: // Parameters:
// public_ns_sonames [IN] the name of "public" libraries. // public_ns_sonames [IN] the name of "public" libraries.
@ -269,11 +294,10 @@ struct NativeBridgeCallbacks {
// //
// Starting with v3, NativeBridge has two scenarios: with/without namespace. // Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario. // Should not use in non-namespace scenario.
bool (*initNamespace)(const char* public_ns_sonames, bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);
const char* anon_ns_library_path);
// Create new namespace in which native libraries will be loaded.
// Create a namespace and pass the key of releated namespaces to native bridge. // NativeBridge's peer of android_create_namespace() of dynamic linker.
// //
// Parameters: // Parameters:
// name [IN] the name of the namespace. // name [IN] the name of the namespace.
@ -294,7 +318,25 @@ struct NativeBridgeCallbacks {
const char* permitted_when_isolated_path, const char* permitted_when_isolated_path,
native_bridge_namespace_t* parent_ns); 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. // Load a shared library within a namespace.
// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
// extension.
// //
// Parameters: // Parameters:
// libpath [IN] path to the shared library // libpath [IN] path to the shared library

View file

@ -573,11 +573,11 @@ bool NativeBridgeIsPathSupported(const char* path) {
return false; return false;
} }
bool NativeBridgeInitNamespace(const char* public_ns_sonames, bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
const char* anon_ns_library_path) { const char* anon_ns_library_path) {
if (NativeBridgeInitialized()) { if (NativeBridgeInitialized()) {
if (isCompatibleWith(NAMESPACE_VERSION)) { 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 { } else {
ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION); 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; 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) { void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
if (NativeBridgeInitialized()) { if (NativeBridgeInitialized()) {
if (isCompatibleWith(NAMESPACE_VERSION)) { if (isCompatibleWith(NAMESPACE_VERSION)) {

View file

@ -24,7 +24,7 @@ test_src_files := \
NativeBridge3UnloadLibrary_test.cpp \ NativeBridge3UnloadLibrary_test.cpp \
NativeBridge3GetError_test.cpp \ NativeBridge3GetError_test.cpp \
NativeBridge3IsPathSupported_test.cpp \ NativeBridge3IsPathSupported_test.cpp \
NativeBridge3InitNamespace_test.cpp \ NativeBridge3InitAnonymousNamespace_test.cpp \
NativeBridge3CreateNamespace_test.cpp \ NativeBridge3CreateNamespace_test.cpp \
NativeBridge3LoadLibraryExt_test.cpp NativeBridge3LoadLibraryExt_test.cpp

View file

@ -76,7 +76,7 @@ extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
return true; return true;
} }
extern "C" bool native_bridge3_initNamespace(const char* /* public_ns_sonames */, extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
const char* /* anon_ns_library_path */) { const char* /* anon_ns_library_path */) {
return true; return true;
} }
@ -91,14 +91,19 @@ native_bridge3_createNamespace(const char* /* name */,
return nullptr; 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 */, extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
int /* flag */, int /* flag */,
android::native_bridge_namespace_t* /* ns */) { android::native_bridge_namespace_t* /* ns */) {
return nullptr; return nullptr;
} }
android::NativeBridgeCallbacks NativeBridgeItf{
android::NativeBridgeCallbacks NativeBridgeItf {
// v1 // v1
.version = 3, .version = 3,
.initialize = &native_bridge3_initialize, .initialize = &native_bridge3_initialize,
@ -113,8 +118,7 @@ android::NativeBridgeCallbacks NativeBridgeItf {
.unloadLibrary = &native_bridge3_unloadLibrary, .unloadLibrary = &native_bridge3_unloadLibrary,
.getError = &native_bridge3_getError, .getError = &native_bridge3_getError,
.isPathSupported = &native_bridge3_isPathSupported, .isPathSupported = &native_bridge3_isPathSupported,
.initNamespace = &native_bridge3_initNamespace, .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
.createNamespace = &native_bridge3_createNamespace, .createNamespace = &native_bridge3_createNamespace,
.loadLibraryExt = &native_bridge3_loadLibraryExt .linkNamespaces = &native_bridge3_linkNamespaces,
}; .loadLibraryExt = &native_bridge3_loadLibraryExt};

View file

@ -20,7 +20,7 @@ namespace android {
constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so"; constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
TEST_F(NativeBridgeTest, V3_InitNamespace) { TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
// Init // Init
ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr)); ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
ASSERT_TRUE(NativeBridgeAvailable()); ASSERT_TRUE(NativeBridgeAvailable());
@ -30,7 +30,7 @@ TEST_F(NativeBridgeTest, V3_InitNamespace) {
ASSERT_TRUE(NativeBridgeAvailable()); ASSERT_TRUE(NativeBridgeAvailable());
ASSERT_EQ(3U, NativeBridgeGetVersion()); ASSERT_EQ(3U, NativeBridgeGetVersion());
ASSERT_EQ(true, NativeBridgeInitNamespace(nullptr, nullptr)); ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));
// Clean-up code_cache // Clean-up code_cache
ASSERT_EQ(0, rmdir(kCodeCache)); ASSERT_EQ(0, rmdir(kCodeCache));

View file

@ -183,6 +183,11 @@ class LibraryNamespaces {
return false; return false;
} }
if (!NativeBridgeLinkNamespaces(ns, nullptr, public_libraries_.c_str())) {
*error_msg = NativeBridgeGetError();
return false;
}
native_loader_ns = NativeLoaderNamespace(ns); native_loader_ns = NativeLoaderNamespace(ns);
} }
@ -324,7 +329,7 @@ class LibraryNamespaces {
// and now initialize native bridge namespaces if necessary. // and now initialize native bridge namespaces if necessary.
if (NativeBridgeInitialized()) { if (NativeBridgeInitialized()) {
initialized_ = NativeBridgeInitNamespace(public_libraries_.c_str(), initialized_ = NativeBridgeInitAnonymousNamespace(public_libraries_.c_str(),
is_native_bridge ? library_path : nullptr); is_native_bridge ? library_path : nullptr);
if (!initialized_) { if (!initialized_) {
*error_msg = NativeBridgeGetError(); *error_msg = NativeBridgeGetError();