Merge "NativeBridge: add "linked namespace" semantic corresponding to linker"
am: 1238292db5
Change-Id: I9200efa2d6c3f0d1b96b81e5c065f85f8b96b06f
This commit is contained in:
commit
21c8a291c5
6 changed files with 137 additions and 73 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue