Merge "Use android::base::Result in libnativeloader"
This commit is contained in:
commit
244d9b8fb9
|
@ -33,6 +33,8 @@
|
|||
#include "public_libraries.h"
|
||||
#include "utils.h"
|
||||
|
||||
using android::base::Error;
|
||||
|
||||
namespace android::nativeloader {
|
||||
|
||||
namespace {
|
||||
|
@ -128,11 +130,11 @@ void LibraryNamespaces::Initialize() {
|
|||
}
|
||||
}
|
||||
|
||||
NativeLoaderNamespace* LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
|
||||
jobject class_loader, bool is_shared,
|
||||
jstring dex_path, jstring java_library_path,
|
||||
jstring java_permitted_path,
|
||||
std::string* error_msg) {
|
||||
Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
|
||||
jobject class_loader, bool is_shared,
|
||||
jstring dex_path,
|
||||
jstring java_library_path,
|
||||
jstring java_permitted_path) {
|
||||
std::string library_path; // empty string by default.
|
||||
|
||||
if (java_library_path != nullptr) {
|
||||
|
@ -158,14 +160,14 @@ NativeLoaderNamespace* LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sd
|
|||
}
|
||||
|
||||
// Initialize the anonymous namespace with the first non-empty library path.
|
||||
Result<void> ret;
|
||||
if (!library_path.empty() && !initialized_ &&
|
||||
!InitPublicNamespace(library_path.c_str(), error_msg)) {
|
||||
return nullptr;
|
||||
!(ret = InitPublicNamespace(library_path.c_str()))) {
|
||||
return ret.error();
|
||||
}
|
||||
|
||||
bool found = FindNamespaceByClassLoader(env, class_loader);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(found, "There is already a namespace associated with this classloader");
|
||||
LOG_ALWAYS_FATAL_IF(FindNamespaceByClassLoader(env, class_loader) != nullptr,
|
||||
"There is already a namespace associated with this classloader");
|
||||
|
||||
std::string system_exposed_libraries = default_public_libraries();
|
||||
const char* namespace_name = kClassloaderNamespaceName;
|
||||
|
@ -216,58 +218,66 @@ NativeLoaderNamespace* LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sd
|
|||
auto app_ns =
|
||||
NativeLoaderNamespace::Create(namespace_name, library_path, permitted_path, parent_ns,
|
||||
is_shared, target_sdk_version < 24 /* is_greylist_enabled */);
|
||||
if (app_ns.IsNil()) {
|
||||
*error_msg = app_ns.GetError();
|
||||
return nullptr;
|
||||
if (!app_ns) {
|
||||
return app_ns.error();
|
||||
}
|
||||
|
||||
// ... and link to other namespaces to allow access to some public libraries
|
||||
bool is_bridged = app_ns.IsBridged();
|
||||
bool is_bridged = app_ns->IsBridged();
|
||||
|
||||
auto platform_ns = NativeLoaderNamespace::GetPlatformNamespace(is_bridged);
|
||||
if (!app_ns.Link(platform_ns, system_exposed_libraries)) {
|
||||
*error_msg = app_ns.GetError();
|
||||
return nullptr;
|
||||
if (!platform_ns) {
|
||||
return platform_ns.error();
|
||||
}
|
||||
|
||||
auto linked = app_ns->Link(*platform_ns, system_exposed_libraries);
|
||||
if (!linked) {
|
||||
return linked.error();
|
||||
}
|
||||
|
||||
auto runtime_ns = NativeLoaderNamespace::GetExportedNamespace(kRuntimeNamespaceName, is_bridged);
|
||||
// Runtime apex does not exist in host, and under certain build conditions.
|
||||
if (!runtime_ns.IsNil()) {
|
||||
if (!app_ns.Link(runtime_ns, runtime_public_libraries())) {
|
||||
*error_msg = app_ns.GetError();
|
||||
return nullptr;
|
||||
if (runtime_ns) {
|
||||
linked = app_ns->Link(*runtime_ns, runtime_public_libraries());
|
||||
if (!linked) {
|
||||
return linked.error();
|
||||
}
|
||||
}
|
||||
|
||||
// Give access to NNAPI libraries (apex-updated LLNDK library).
|
||||
auto nnapi_ns =
|
||||
NativeLoaderNamespace::GetExportedNamespace(kNeuralNetworksNamespaceName, is_bridged);
|
||||
if (!app_ns.Link(nnapi_ns, neuralnetworks_public_libraries())) {
|
||||
*error_msg = app_ns.GetError();
|
||||
return nullptr;
|
||||
if (nnapi_ns) {
|
||||
linked = app_ns->Link(*nnapi_ns, neuralnetworks_public_libraries());
|
||||
if (!linked) {
|
||||
return linked.error();
|
||||
}
|
||||
}
|
||||
|
||||
// Give access to VNDK-SP libraries from the 'vndk' namespace.
|
||||
if (unbundled_vendor_or_product_app && !vndksp_libraries().empty()) {
|
||||
auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
|
||||
if (!vndk_ns.IsNil() && !app_ns.Link(vndk_ns, vndksp_libraries())) {
|
||||
*error_msg = app_ns.GetError();
|
||||
return nullptr;
|
||||
if (vndk_ns) {
|
||||
linked = app_ns->Link(*vndk_ns, vndksp_libraries());
|
||||
if (!linked) {
|
||||
return linked.error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note that when vendor_ns is not configured, vendor_ns.IsNil() will be true
|
||||
// and it will result in linking to the default namespace which is expected
|
||||
// behavior in this case.
|
||||
if (!vendor_public_libraries().empty()) {
|
||||
auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
|
||||
if (!app_ns.Link(vendor_ns, vendor_public_libraries())) {
|
||||
*error_msg = dlerror();
|
||||
return nullptr;
|
||||
// when vendor_ns is not configured, link to the platform namespace
|
||||
auto target_ns = vendor_ns ? vendor_ns : platform_ns;
|
||||
if (target_ns) {
|
||||
linked = app_ns->Link(*target_ns, vendor_public_libraries());
|
||||
if (!linked) {
|
||||
return linked.error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), app_ns));
|
||||
namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
|
||||
|
||||
return &(namespaces_.back().second);
|
||||
}
|
||||
|
@ -285,7 +295,7 @@ NativeLoaderNamespace* LibraryNamespaces::FindNamespaceByClassLoader(JNIEnv* env
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool LibraryNamespaces::InitPublicNamespace(const char* library_path, std::string* error_msg) {
|
||||
Result<void> LibraryNamespaces::InitPublicNamespace(const char* library_path) {
|
||||
// Ask native bride if this apps library path should be handled by it
|
||||
bool is_native_bridge = NativeBridgeIsPathSupported(library_path);
|
||||
|
||||
|
@ -296,8 +306,7 @@ bool LibraryNamespaces::InitPublicNamespace(const char* library_path, std::strin
|
|||
initialized_ = android_init_anonymous_namespace(default_public_libraries().c_str(),
|
||||
is_native_bridge ? nullptr : library_path);
|
||||
if (!initialized_) {
|
||||
*error_msg = dlerror();
|
||||
return false;
|
||||
return Error() << dlerror();
|
||||
}
|
||||
|
||||
// and now initialize native bridge namespaces if necessary.
|
||||
|
@ -305,11 +314,11 @@ bool LibraryNamespaces::InitPublicNamespace(const char* library_path, std::strin
|
|||
initialized_ = NativeBridgeInitAnonymousNamespace(default_public_libraries().c_str(),
|
||||
is_native_bridge ? library_path : nullptr);
|
||||
if (!initialized_) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
return Error() << NativeBridgeGetError();
|
||||
}
|
||||
}
|
||||
|
||||
return initialized_;
|
||||
return {};
|
||||
}
|
||||
|
||||
NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEnv* env,
|
||||
|
|
|
@ -25,10 +25,13 @@
|
|||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include <android-base/result.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace android::nativeloader {
|
||||
|
||||
using android::base::Result;
|
||||
|
||||
// LibraryNamespaces is a singleton object that manages NativeLoaderNamespace
|
||||
// objects for an app process. Its main job is to create (and configure) a new
|
||||
// NativeLoaderNamespace object for a Java ClassLoader, and to find an existing
|
||||
|
@ -46,13 +49,13 @@ class LibraryNamespaces {
|
|||
namespaces_.clear();
|
||||
initialized_ = false;
|
||||
}
|
||||
NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
|
||||
bool is_shared, jstring dex_path, jstring java_library_path,
|
||||
jstring java_permitted_path, std::string* error_msg);
|
||||
Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version,
|
||||
jobject class_loader, bool is_shared, jstring dex_path,
|
||||
jstring java_library_path, jstring java_permitted_path);
|
||||
NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
|
||||
|
||||
private:
|
||||
bool InitPublicNamespace(const char* library_path, std::string* error_msg);
|
||||
Result<void> InitPublicNamespace(const char* library_path);
|
||||
NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
|
||||
|
||||
bool initialized_;
|
||||
|
|
|
@ -92,12 +92,10 @@ jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobj
|
|||
jstring permitted_path) {
|
||||
#if defined(__ANDROID__)
|
||||
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
|
||||
|
||||
std::string error_msg;
|
||||
bool success = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
|
||||
library_path, permitted_path, &error_msg) != nullptr;
|
||||
if (!success) {
|
||||
return env->NewStringUTF(error_msg.c_str());
|
||||
auto ns = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
|
||||
library_path, permitted_path);
|
||||
if (!ns) {
|
||||
return env->NewStringUTF(ns.error().message().c_str());
|
||||
}
|
||||
#else
|
||||
UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
|
||||
|
@ -139,11 +137,14 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat
|
|||
if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
|
||||
// This is the case where the classloader was not created by ApplicationLoaders
|
||||
// In this case we create an isolated not-shared namespace for it.
|
||||
std::string create_error_msg;
|
||||
if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
|
||||
nullptr, library_path, nullptr, &create_error_msg)) == nullptr) {
|
||||
*error_msg = strdup(create_error_msg.c_str());
|
||||
Result<NativeLoaderNamespace*> isolated_ns =
|
||||
g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, nullptr,
|
||||
library_path, nullptr);
|
||||
if (!isolated_ns) {
|
||||
*error_msg = strdup(isolated_ns.error().message().c_str());
|
||||
return nullptr;
|
||||
} else {
|
||||
ns = *isolated_ns;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,12 +223,14 @@ void NativeLoaderFreeErrorMessage(char* msg) {
|
|||
#if defined(__ANDROID__)
|
||||
void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
|
||||
bool* needs_native_bridge, char** error_msg) {
|
||||
void* handle = ns->Load(path);
|
||||
if (handle == nullptr) {
|
||||
*error_msg = ns->GetError();
|
||||
auto handle = ns->Load(path);
|
||||
if (!handle && error_msg != nullptr) {
|
||||
*error_msg = strdup(handle.error().message().c_str());
|
||||
}
|
||||
*needs_native_bridge = ns->IsBridged();
|
||||
return handle;
|
||||
if (needs_native_bridge != nullptr) {
|
||||
*needs_native_bridge = ns->IsBridged();
|
||||
}
|
||||
return handle ? *handle : nullptr;
|
||||
}
|
||||
|
||||
// native_bridge_namespaces are not supported for callers of this function.
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
#include "nativeloader/dlext_namespaces.h"
|
||||
|
||||
using android::base::Error;
|
||||
using android::base::Errorf;
|
||||
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
|
@ -35,41 +38,46 @@ namespace {
|
|||
constexpr const char* kDefaultNamespaceName = "default";
|
||||
constexpr const char* kPlatformNamespaceName = "platform";
|
||||
|
||||
} // namespace
|
||||
|
||||
NativeLoaderNamespace NativeLoaderNamespace::GetExportedNamespace(const std::string& name,
|
||||
bool is_bridged) {
|
||||
if (!is_bridged) {
|
||||
return NativeLoaderNamespace(name, android_get_exported_namespace(name.c_str()));
|
||||
} else {
|
||||
return NativeLoaderNamespace(name, NativeBridgeGetExportedNamespace(name.c_str()));
|
||||
std::string GetLinkerError(bool is_bridged) {
|
||||
const char* msg = is_bridged ? NativeBridgeGetError() : dlerror();
|
||||
if (msg == nullptr) {
|
||||
return "no error";
|
||||
}
|
||||
return std::string(msg);
|
||||
}
|
||||
|
||||
char* NativeLoaderNamespace::GetError() const {
|
||||
if (!IsBridged()) {
|
||||
return strdup(dlerror());
|
||||
} // namespace
|
||||
|
||||
Result<NativeLoaderNamespace> NativeLoaderNamespace::GetExportedNamespace(const std::string& name,
|
||||
bool is_bridged) {
|
||||
if (!is_bridged) {
|
||||
auto raw = android_get_exported_namespace(name.c_str());
|
||||
if (raw != nullptr) {
|
||||
return NativeLoaderNamespace(name, raw);
|
||||
}
|
||||
} else {
|
||||
return strdup(NativeBridgeGetError());
|
||||
auto raw = NativeBridgeGetExportedNamespace(name.c_str());
|
||||
if (raw != nullptr) {
|
||||
return NativeLoaderNamespace(name, raw);
|
||||
}
|
||||
}
|
||||
return Errorf("namespace {} does not exist or exported", name);
|
||||
}
|
||||
|
||||
// The platform namespace is called "default" for binaries in /system and
|
||||
// "platform" for those in the Runtime APEX. Try "platform" first since
|
||||
// "default" always exists.
|
||||
NativeLoaderNamespace NativeLoaderNamespace::GetPlatformNamespace(bool is_bridged) {
|
||||
NativeLoaderNamespace ns = GetExportedNamespace(kPlatformNamespaceName, is_bridged);
|
||||
if (ns.IsNil()) {
|
||||
Result<NativeLoaderNamespace> NativeLoaderNamespace::GetPlatformNamespace(bool is_bridged) {
|
||||
auto ns = GetExportedNamespace(kPlatformNamespaceName, is_bridged);
|
||||
if (!ns) {
|
||||
ns = GetExportedNamespace(kDefaultNamespaceName, is_bridged);
|
||||
}
|
||||
return ns;
|
||||
}
|
||||
|
||||
NativeLoaderNamespace NativeLoaderNamespace::Create(const std::string& name,
|
||||
const std::string& search_paths,
|
||||
const std::string& permitted_paths,
|
||||
const NativeLoaderNamespace* parent,
|
||||
bool is_shared, bool is_greylist_enabled) {
|
||||
Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
|
||||
const std::string& name, const std::string& search_paths, const std::string& permitted_paths,
|
||||
const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled) {
|
||||
bool is_bridged = false;
|
||||
if (parent != nullptr) {
|
||||
is_bridged = parent->IsBridged();
|
||||
|
@ -78,8 +86,11 @@ NativeLoaderNamespace NativeLoaderNamespace::Create(const std::string& name,
|
|||
}
|
||||
|
||||
// Fall back to the platform namespace if no parent is set.
|
||||
const NativeLoaderNamespace& effective_parent =
|
||||
parent != nullptr ? *parent : GetPlatformNamespace(is_bridged);
|
||||
auto platform_ns = GetPlatformNamespace(is_bridged);
|
||||
if (!platform_ns) {
|
||||
return platform_ns.error();
|
||||
}
|
||||
const NativeLoaderNamespace& effective_parent = parent != nullptr ? *parent : *platform_ns;
|
||||
|
||||
uint64_t type = ANDROID_NAMESPACE_TYPE_ISOLATED;
|
||||
if (is_shared) {
|
||||
|
@ -93,37 +104,56 @@ NativeLoaderNamespace NativeLoaderNamespace::Create(const std::string& name,
|
|||
android_namespace_t* raw =
|
||||
android_create_namespace(name.c_str(), nullptr, search_paths.c_str(), type,
|
||||
permitted_paths.c_str(), effective_parent.ToRawAndroidNamespace());
|
||||
return NativeLoaderNamespace(name, raw);
|
||||
if (raw != nullptr) {
|
||||
return NativeLoaderNamespace(name, raw);
|
||||
}
|
||||
} else {
|
||||
native_bridge_namespace_t* raw = NativeBridgeCreateNamespace(
|
||||
name.c_str(), nullptr, search_paths.c_str(), type, permitted_paths.c_str(),
|
||||
effective_parent.ToRawNativeBridgeNamespace());
|
||||
return NativeLoaderNamespace(name, raw);
|
||||
if (raw != nullptr) {
|
||||
return NativeLoaderNamespace(name, raw);
|
||||
}
|
||||
}
|
||||
return Errorf("failed to create {} namespace name:{}, search_paths:{}, permitted_paths:{}",
|
||||
is_bridged ? "bridged" : "native", name, search_paths, permitted_paths);
|
||||
}
|
||||
|
||||
bool NativeLoaderNamespace::Link(const NativeLoaderNamespace& target,
|
||||
const std::string& shared_libs) const {
|
||||
Result<void> NativeLoaderNamespace::Link(const NativeLoaderNamespace& target,
|
||||
const std::string& shared_libs) const {
|
||||
LOG_ALWAYS_FATAL_IF(shared_libs.empty(), "empty share lib when linking %s to %s",
|
||||
this->name().c_str(), target.name().c_str());
|
||||
if (!IsBridged()) {
|
||||
return android_link_namespaces(this->ToRawAndroidNamespace(), target.ToRawAndroidNamespace(),
|
||||
shared_libs.c_str());
|
||||
if (android_link_namespaces(this->ToRawAndroidNamespace(), target.ToRawAndroidNamespace(),
|
||||
shared_libs.c_str())) {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
return NativeBridgeLinkNamespaces(this->ToRawNativeBridgeNamespace(),
|
||||
target.ToRawNativeBridgeNamespace(), shared_libs.c_str());
|
||||
if (NativeBridgeLinkNamespaces(this->ToRawNativeBridgeNamespace(),
|
||||
target.ToRawNativeBridgeNamespace(), shared_libs.c_str())) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return Error() << GetLinkerError(IsBridged());
|
||||
}
|
||||
|
||||
void* NativeLoaderNamespace::Load(const char* lib_name) const {
|
||||
Result<void*> NativeLoaderNamespace::Load(const char* lib_name) const {
|
||||
if (!IsBridged()) {
|
||||
android_dlextinfo extinfo;
|
||||
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||
extinfo.library_namespace = this->ToRawAndroidNamespace();
|
||||
return android_dlopen_ext(lib_name, RTLD_NOW, &extinfo);
|
||||
void* handle = android_dlopen_ext(lib_name, RTLD_NOW, &extinfo);
|
||||
if (handle != nullptr) {
|
||||
return handle;
|
||||
}
|
||||
} else {
|
||||
return NativeBridgeLoadLibraryExt(lib_name, RTLD_NOW, this->ToRawNativeBridgeNamespace());
|
||||
void* handle =
|
||||
NativeBridgeLoadLibraryExt(lib_name, RTLD_NOW, this->ToRawNativeBridgeNamespace());
|
||||
if (handle != nullptr) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
return Error() << GetLinkerError(IsBridged());
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
|
|
@ -21,22 +21,25 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/result.h>
|
||||
#include <android/dlext.h>
|
||||
#include <log/log.h>
|
||||
#include <nativebridge/native_bridge.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
using android::base::Result;
|
||||
|
||||
// NativeLoaderNamespace abstracts a linker namespace for the native
|
||||
// architecture (ex: arm on arm) or the translated architecture (ex: arm on
|
||||
// x86). Instances of this class are managed by LibraryNamespaces object.
|
||||
struct NativeLoaderNamespace {
|
||||
public:
|
||||
// TODO(return with errors)
|
||||
static NativeLoaderNamespace Create(const std::string& name, const std::string& search_paths,
|
||||
const std::string& permitted_paths,
|
||||
const NativeLoaderNamespace* parent, bool is_shared,
|
||||
bool is_greylist_enabled);
|
||||
static Result<NativeLoaderNamespace> Create(const std::string& name,
|
||||
const std::string& search_paths,
|
||||
const std::string& permitted_paths,
|
||||
const NativeLoaderNamespace* parent, bool is_shared,
|
||||
bool is_greylist_enabled);
|
||||
|
||||
NativeLoaderNamespace(NativeLoaderNamespace&&) = default;
|
||||
NativeLoaderNamespace(const NativeLoaderNamespace&) = default;
|
||||
|
@ -47,16 +50,13 @@ struct NativeLoaderNamespace {
|
|||
|
||||
std::string name() const { return name_; }
|
||||
bool IsBridged() const { return raw_.index() == 1; }
|
||||
bool IsNil() const {
|
||||
return IsBridged() ? std::get<1>(raw_) == nullptr : std::get<0>(raw_) == nullptr;
|
||||
}
|
||||
|
||||
bool Link(const NativeLoaderNamespace& target, const std::string& shared_libs) const;
|
||||
void* Load(const char* lib_name) const;
|
||||
char* GetError() const;
|
||||
Result<void> Link(const NativeLoaderNamespace& target, const std::string& shared_libs) const;
|
||||
Result<void*> Load(const char* lib_name) const;
|
||||
|
||||
static NativeLoaderNamespace GetExportedNamespace(const std::string& name, bool is_bridged);
|
||||
static NativeLoaderNamespace GetPlatformNamespace(bool is_bridged);
|
||||
static Result<NativeLoaderNamespace> GetExportedNamespace(const std::string& name,
|
||||
bool is_bridged);
|
||||
static Result<NativeLoaderNamespace> GetPlatformNamespace(bool is_bridged);
|
||||
|
||||
private:
|
||||
explicit NativeLoaderNamespace(const std::string& name, android_namespace_t* ns)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/result.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <log/log.h>
|
||||
|
||||
|
@ -34,6 +35,9 @@
|
|||
namespace android::nativeloader {
|
||||
|
||||
using namespace std::string_literals;
|
||||
using android::base::ErrnoError;
|
||||
using android::base::Errorf;
|
||||
using android::base::Result;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -91,22 +95,21 @@ void InsertVndkVersionStr(std::string* file_name) {
|
|||
file_name->insert(insert_pos, vndk_version_str());
|
||||
}
|
||||
|
||||
const std::function<bool(const std::string&, std::string*)> always_true =
|
||||
[](const std::string&, std::string*) { return true; };
|
||||
const std::function<Result<void>(const std::string&)> always_true =
|
||||
[](const std::string&) -> Result<void> { return {}; };
|
||||
|
||||
bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames,
|
||||
const std::function<bool(const std::string& /* soname */,
|
||||
std::string* /* error_msg */)>& check_soname,
|
||||
std::string* error_msg = nullptr) {
|
||||
Result<std::vector<std::string>> ReadConfig(
|
||||
const std::string& configFile,
|
||||
const std::function<Result<void>(const std::string& /* soname */)>& check_soname) {
|
||||
// Read list of public native libraries from the config file.
|
||||
std::string file_content;
|
||||
if (!base::ReadFileToString(configFile, &file_content)) {
|
||||
if (error_msg) *error_msg = strerror(errno);
|
||||
return false;
|
||||
return ErrnoError();
|
||||
}
|
||||
|
||||
std::vector<std::string> lines = base::Split(file_content, "\n");
|
||||
|
||||
std::vector<std::string> sonames;
|
||||
for (auto& line : lines) {
|
||||
auto trimmed_line = base::Trim(line);
|
||||
if (trimmed_line[0] == '#' || trimmed_line.empty()) {
|
||||
|
@ -116,8 +119,7 @@ bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames
|
|||
if (space_pos != std::string::npos) {
|
||||
std::string type = trimmed_line.substr(space_pos + 1);
|
||||
if (type != "32" && type != "64") {
|
||||
if (error_msg) *error_msg = "Malformed line: " + line;
|
||||
return false;
|
||||
return Errorf("Malformed line: {}", line);
|
||||
}
|
||||
#if defined(__LP64__)
|
||||
// Skip 32 bit public library.
|
||||
|
@ -133,13 +135,13 @@ bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames
|
|||
trimmed_line.resize(space_pos);
|
||||
}
|
||||
|
||||
if (check_soname(trimmed_line, error_msg)) {
|
||||
sonames->push_back(trimmed_line);
|
||||
} else {
|
||||
return false;
|
||||
auto ret = check_soname(trimmed_line);
|
||||
if (!ret) {
|
||||
return ret.error();
|
||||
}
|
||||
sonames.push_back(trimmed_line);
|
||||
}
|
||||
return true;
|
||||
return sonames;
|
||||
}
|
||||
|
||||
void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) {
|
||||
|
@ -162,24 +164,22 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam
|
|||
"Error extracting company name from public native library list file path \"%s\"",
|
||||
config_file_path.c_str());
|
||||
|
||||
std::string error_msg;
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
!ReadConfig(config_file_path, sonames,
|
||||
[&company_name](const std::string& soname, std::string* error_msg) {
|
||||
if (android::base::StartsWith(soname, "lib") &&
|
||||
android::base::EndsWith(soname, "." + company_name + ".so")) {
|
||||
return true;
|
||||
} else {
|
||||
*error_msg = "Library name \"" + soname +
|
||||
"\" does not end with the company name: " + company_name +
|
||||
".";
|
||||
return false;
|
||||
}
|
||||
},
|
||||
&error_msg),
|
||||
"Error reading public native library list from \"%s\": %s", config_file_path.c_str(),
|
||||
error_msg.c_str());
|
||||
auto ret = ReadConfig(
|
||||
config_file_path, [&company_name](const std::string& soname) -> Result<void> {
|
||||
if (android::base::StartsWith(soname, "lib") &&
|
||||
android::base::EndsWith(soname, "." + company_name + ".so")) {
|
||||
return {};
|
||||
} else {
|
||||
return Errorf("Library name \"{}\" does not end with the company name {}.", soname,
|
||||
company_name);
|
||||
}
|
||||
});
|
||||
if (ret) {
|
||||
sonames->insert(sonames->end(), ret->begin(), ret->end());
|
||||
} else {
|
||||
LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s",
|
||||
config_file_path.c_str(), ret.error().message().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,16 +187,17 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam
|
|||
|
||||
static std::string InitDefaultPublicLibraries() {
|
||||
std::string config_file = root_dir() + kDefaultPublicLibrariesFile;
|
||||
std::vector<std::string> sonames;
|
||||
std::string error_msg;
|
||||
LOG_ALWAYS_FATAL_IF(!ReadConfig(config_file, &sonames, always_true, &error_msg),
|
||||
"Error reading public native library list from \"%s\": %s",
|
||||
config_file.c_str(), error_msg.c_str());
|
||||
auto sonames = ReadConfig(config_file, always_true);
|
||||
if (!sonames) {
|
||||
LOG_ALWAYS_FATAL("Error reading public native library list from \"%s\": %s",
|
||||
config_file.c_str(), sonames.error().message().c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string additional_libs = additional_public_libraries();
|
||||
if (!additional_libs.empty()) {
|
||||
auto vec = base::Split(additional_libs, ":");
|
||||
std::copy(vec.begin(), vec.end(), std::back_inserter(sonames));
|
||||
std::copy(vec.begin(), vec.end(), std::back_inserter(*sonames));
|
||||
}
|
||||
|
||||
// Remove the public libs in the runtime namespace.
|
||||
|
@ -216,18 +217,18 @@ static std::string InitDefaultPublicLibraries() {
|
|||
continue;
|
||||
}
|
||||
|
||||
auto it = std::find(sonames.begin(), sonames.end(), lib_name);
|
||||
if (it != sonames.end()) {
|
||||
sonames.erase(it);
|
||||
auto it = std::find(sonames->begin(), sonames->end(), lib_name);
|
||||
if (it != sonames->end()) {
|
||||
sonames->erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the public libs in the nnapi namespace.
|
||||
auto it = std::find(sonames.begin(), sonames.end(), kNeuralNetworksApexPublicLibrary);
|
||||
if (it != sonames.end()) {
|
||||
sonames.erase(it);
|
||||
auto it = std::find(sonames->begin(), sonames->end(), kNeuralNetworksApexPublicLibrary);
|
||||
if (it != sonames->end()) {
|
||||
sonames->erase(it);
|
||||
}
|
||||
return android::base::Join(sonames, ':');
|
||||
return android::base::Join(*sonames, ':');
|
||||
}
|
||||
|
||||
static std::string InitRuntimePublicLibraries() {
|
||||
|
@ -243,9 +244,11 @@ static std::string InitRuntimePublicLibraries() {
|
|||
|
||||
static std::string InitVendorPublicLibraries() {
|
||||
// This file is optional, quietly ignore if the file does not exist.
|
||||
std::vector<std::string> sonames;
|
||||
ReadConfig(kVendorPublicLibrariesFile, &sonames, always_true, nullptr);
|
||||
return android::base::Join(sonames, ':');
|
||||
auto sonames = ReadConfig(kVendorPublicLibrariesFile, always_true);
|
||||
if (!sonames) {
|
||||
return "";
|
||||
}
|
||||
return android::base::Join(*sonames, ':');
|
||||
}
|
||||
|
||||
// read /system/etc/public.libraries-<companyname>.txt and
|
||||
|
@ -262,17 +265,23 @@ static std::string InitExtendedPublicLibraries() {
|
|||
static std::string InitLlndkLibraries() {
|
||||
std::string config_file = kLlndkLibrariesFile;
|
||||
InsertVndkVersionStr(&config_file);
|
||||
std::vector<std::string> sonames;
|
||||
ReadConfig(config_file, &sonames, always_true, nullptr);
|
||||
return android::base::Join(sonames, ':');
|
||||
auto sonames = ReadConfig(config_file, always_true);
|
||||
if (!sonames) {
|
||||
LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
|
||||
return "";
|
||||
}
|
||||
return android::base::Join(*sonames, ':');
|
||||
}
|
||||
|
||||
static std::string InitVndkspLibraries() {
|
||||
std::string config_file = kVndkLibrariesFile;
|
||||
InsertVndkVersionStr(&config_file);
|
||||
std::vector<std::string> sonames;
|
||||
ReadConfig(config_file, &sonames, always_true, nullptr);
|
||||
return android::base::Join(sonames, ':');
|
||||
auto sonames = ReadConfig(config_file, always_true);
|
||||
if (!sonames) {
|
||||
LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
|
||||
return "";
|
||||
}
|
||||
return android::base::Join(*sonames, ':');
|
||||
}
|
||||
|
||||
static std::string InitNeuralNetworksPublicLibraries() {
|
||||
|
|
Loading…
Reference in New Issue