Android system — 链接器命名空间共享库设置方法(Android 11后) ...

打印 上一主题 下一主题

主题 833|帖子 833|积分 2499

1. 应用进程

1.1 应用进程类加载器的命名空间初始化

  在应用步伐对应的可执行文件app_process根据/linkerconfig/ld.config.txt设置文件初始化命名空间之后,每当应用步伐创建一个类加载器classloader并调用System.loadLibrary加载so库时都会创建一个与此类加载器对应的命名空间。从源码角度分析一下这个过程,System.loadLibrary函数末了会调用OpenNativeLibrary函数。
1.1.1 OpenNativeLibrary

System.loadLibrary()-->nativeLoad()-->Runtime.c::Runtime_nativeLoad()-->JVM_NativeLoad()-->Openjdkjvm.cc::JVM_NativeLoad()-->java_vm_ext.cc:oadNativeLibrary()-->native_loader.cpp::OpenNativeLibrary() 也就是java层的System.loadLibrary()终极会调用libnativeloader.so的OpenNativeLibrary函数。


  • OpenNativeLibrary先判断classloader类加载器是否为空,如果为空直接调用android_dlopen_ext加载库文件
  • 如果判断classloader类加载器不为空,并且classloader类加载器没有对应的命名空间(第一次调用System.loadLibrary)就调用LibraryNamespaces::Create创建新的命名空间。
  1. void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
  2.                         jobject class_loader, const char* caller_location, jstring library_path,
  3.                         bool* needs_native_bridge, char** error_msg) {
  4. #if defined(ART_TARGET_ANDROID)
  5.   UNUSED(target_sdk_version);
  6.   if (class_loader == nullptr) { //如果类加载器为空直接调用android_dlopen_ext加载库文件
  7.     *needs_native_bridge = false;
  8.     if (caller_location != nullptr) {
  9.       android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
  10.       if (boot_namespace != nullptr) {
  11.         const android_dlextinfo dlextinfo = {
  12.             .flags = ANDROID_DLEXT_USE_NAMESPACE,
  13.             .library_namespace = boot_namespace,
  14.         };
  15.         void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
  16.         if (handle == nullptr) {
  17.           *error_msg = strdup(dlerror());
  18.         }
  19.         return handle;
  20.       }
  21.     }
  22.     // Check if the library is in NATIVELOADER_DEFAULT_NAMESPACE_LIBS and should
  23.     // be loaded from the kNativeloaderExtraLibs namespace.
  24.     {
  25.       Result<void*> handle = TryLoadNativeloaderExtraLib(path);
  26.       if (!handle.ok()) {
  27.         *error_msg = strdup(handle.error().message().c_str());
  28.         return nullptr;
  29.       }
  30.       if (handle.value() != nullptr) {
  31.         return handle.value();
  32.       }
  33.     }
  34.     // Fall back to the system namespace. This happens for preloaded JNI
  35.     // libraries in the zygote.
  36.     // TODO(b/185833744): Investigate if this should fall back to the app main
  37.     // namespace (aka anonymous namespace) instead.
  38.     void* handle = OpenSystemLibrary(path, RTLD_NOW);
  39.     if (handle == nullptr) {
  40.       *error_msg = strdup(dlerror());
  41.     }
  42.     return handle;
  43.   }
  44.   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
  45.   NativeLoaderNamespace* ns;
  46.   if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) { //如果类加载器不为空,且类加载器没有对应的命名空间就新创建一个
  47.     // This is the case where the classloader was not created by ApplicationLoaders
  48.     // In this case we create an isolated not-shared namespace for it.
  49.     Result<NativeLoaderNamespace*> isolated_ns =
  50.         CreateClassLoaderNamespaceLocked(env,
  51.                                          target_sdk_version,
  52.                                          class_loader,
  53.                                          /*is_shared=*/false,
  54.                                          /*dex_path=*/nullptr,
  55.                                          library_path,
  56.                                          /*permitted_path=*/nullptr,
  57.                                          /*uses_library_list=*/nullptr);
  58.     if (!isolated_ns.ok()) {
  59.       *error_msg = strdup(isolated_ns.error().message().c_str());
  60.       return nullptr;
  61.     } else {
  62.       ns = *isolated_ns;
  63.     }
  64.   }
  65.   return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
复制代码
在CreateClassLoaderNamespaceLocked中我们可以看到调用了LibraryNamespaces::Create创建新的命名空间
  1. Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env,
  2.                                                                 int32_t target_sdk_version,
  3.                                                                 jobject class_loader,
  4.                                                                 bool is_shared,
  5.                                                                 jstring dex_path,
  6.                                                                 jstring library_path,
  7.                                                                 jstring permitted_path,
  8.                                                                 jstring uses_library_list)
  9.     REQUIRES(g_namespaces_mutex) {
  10.   Result<NativeLoaderNamespace*> ns = g_namespaces->Create(env,
  11.                                                            target_sdk_version,
  12.                                                            class_loader,
  13.                                                            is_shared,
  14.                                                            dex_path,
  15.                                                            library_path,
  16.                                                            permitted_path,
  17.                                                            uses_library_list);
  18.   if (!ns.ok()) {
  19.     return ns;
  20.   }
  21.   Result<void> linked = CreateNativeloaderDefaultNamespaceLibsLink(*ns.value());
  22.   if (!linked.ok()) {
  23.     return linked.error();
  24.   }
  25.   return ns;
  26. }
复制代码
1.1.2 LibraryNamespaces::Create



  • 先调用android_create_namespace创建一个clns命名空间
  • 调用android_linker_namespace设置新创建的命名空间链接到system、APEX和vendor等命名空间
  • 设置链接到system、APEX等命名空间的共享库
  1. Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
  2.                                                          jobject class_loader, bool is_shared,
  3.                                                          jstring dex_path_j,
  4.                                                          jstring java_library_path,
  5.                                                          jstring java_permitted_path,
  6.                                                          jstring uses_library_list) {
  7.   std::string library_path;  // empty string by default.
  8.   std::string dex_path;
  9.   ......
  10.   // Create the app namespace
  11.   NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
  12.   // Heuristic: the first classloader with non-empty library_path is assumed to
  13.   // be the main classloader for app
  14.   // TODO(b/139178525) remove this heuristic by determining this in LoadedApk (or its
  15.   // friends) and then passing it down to here.
  16.   bool is_main_classloader = app_main_namespace_ == nullptr && !library_path.empty();
  17.   // Policy: the namespace for the main classloader is also used as the
  18.   // anonymous namespace.
  19.   bool also_used_as_anonymous = is_main_classloader;
  20.   // Note: this function is executed with g_namespaces_mutex held, thus no
  21.   // racing here.
  22.   //创建命名空间,namespace_name为kClassloaderNamespaceName = "clns"
  23.   auto app_ns = NativeLoaderNamespace::Create(
  24.       namespace_name, library_path, permitted_path, parent_ns, is_shared,
  25.       target_sdk_version < 24 /* is_exempt_list_enabled */, also_used_as_anonymous);
  26.   if (!app_ns.ok()) {
  27.     return app_ns.error();
  28.   }
  29.   // ... and link to other namespaces to allow access to some public libraries
  30.   bool is_bridged = app_ns->IsBridged();
  31.   auto system_ns = NativeLoaderNamespace::GetSystemNamespace(is_bridged);
  32.   if (!system_ns.ok()) {
  33.     return system_ns.error();
  34.   }
  35.   // 新创建的命名空间链接到system,共享库设置为system_exposed_libraries
  36.   auto linked = app_ns->Link(&system_ns.value(), system_exposed_libraries);
  37.   if (!linked.ok()) {
  38.     return linked.error();
  39.   }
  40.   for (const auto&[apex_ns_name, public_libs] : apex_public_libraries()) {
  41.     auto ns = NativeLoaderNamespace::GetExportedNamespace(apex_ns_name, is_bridged);
  42.     // Even if APEX namespace is visible, it may not be available to bridged.
  43.     if (ns.ok()) {
  44.       // 新创建的命名空间链接到APEX,共享库设置为public_libs
  45.       linked = app_ns->Link(&ns.value(), public_libs);
  46.       if (!linked.ok()) {
  47.         return linked.error();
  48.       }
  49.     }
  50.   }
  51.   // Give access to VNDK-SP libraries from the 'vndk' namespace for unbundled vendor apps.
  52.   if (unbundled_app_origin == APK_ORIGIN_VENDOR && !vndksp_libraries_vendor().empty()) {
  53.     auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
  54.     if (vndk_ns.ok()) {
  55.       // 新创建的命名空间链接到vndk,共享库设置为vndksp_libraries_vendor()
  56.       linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_vendor());
  57.       if (!linked.ok()) {
  58.         return linked.error();
  59.       }
  60.     }
  61.   }
  62.   // Give access to VNDK-SP libraries from the 'vndk_product' namespace for unbundled product apps.
  63.   if (unbundled_app_origin == APK_ORIGIN_PRODUCT && !vndksp_libraries_product().empty()) {
  64.     auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkProductNamespaceName, is_bridged);
  65.     if (vndk_ns.ok()) {
  66.       linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_product());
  67.       if (!linked.ok()) {
  68.         return linked.error();
  69.       }
  70.     }
  71.   }
  72.   for (const std::string& each_jar_path : android::base::Split(dex_path, ":")) {
  73.     auto apex_ns_name = FindApexNamespaceName(each_jar_path);
  74.     if (apex_ns_name.ok()) {
  75.       const auto& jni_libs = apex_jni_libraries(*apex_ns_name);
  76.       if (jni_libs != "") {
  77.         auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged);
  78.         if (apex_ns.ok()) {
  79.           linked = app_ns->Link(&apex_ns.value(), jni_libs);
  80.           if (!linked.ok()) {
  81.             return linked.error();
  82.           }
  83.         }
  84.       }
  85.     }
  86.   }
  87.   auto vendor_libs = filter_public_libraries(target_sdk_version, uses_libraries,
  88.                                              vendor_public_libraries());
  89.   if (!vendor_libs.empty()) {
  90.     auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
  91.     // when vendor_ns is not configured, link to the system namespace
  92.     auto target_ns = vendor_ns.ok() ? vendor_ns : system_ns;
  93.     if (target_ns.ok()) {
  94.       linked = app_ns->Link(&target_ns.value(), vendor_libs);
  95.       if (!linked.ok()) {
  96.         return linked.error();
  97.       }
  98.     }
  99.   }
  100.   auto product_libs = filter_public_libraries(target_sdk_version, uses_libraries,
  101.                                               product_public_libraries());
  102.   if (!product_libs.empty()) {
  103.     auto target_ns = system_ns;
  104.     if (is_product_vndk_version_defined()) {
  105.       // If ro.product.vndk.version is defined, product namespace provides the product libraries.
  106.       target_ns = NativeLoaderNamespace::GetExportedNamespace(kProductNamespaceName, is_bridged);
  107.     }
  108.     if (target_ns.ok()) {
  109.       linked = app_ns->Link(&target_ns.value(), product_libs);
  110.       if (!linked.ok()) {
  111.         return linked.error();
  112.       }
  113.     } else {
  114.       // The linkerconfig must have a problem on defining the product namespace in the system
  115.       // section. Skip linking product namespace. This will not affect most of the apps. Only the
  116.       // apps that requires the product public libraries will fail.
  117.       ALOGW("Namespace for product libs not found: %s", target_ns.error().message().c_str());
  118.     }
  119.   }
  120.   auto& emplaced = namespaces_.emplace_back(
  121.       std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
  122.   if (is_main_classloader) {
  123.     app_main_namespace_ = &emplaced.second;
  124.   }
  125.   return &emplaced.second;
  126. }
复制代码
1.2 设置共享库位置

通过上面的代码跟踪我们会发现,实在在Android 11后,应用进程共享库的设置位置都在public_libraries.cpp中
  1. // art/libnativeloader/public_libraries.cpp
  2. namespace {
  3. constexpr const char* kDefaultPublicLibrariesFile = "/etc/public.libraries.txt";
  4. constexpr const char* kExtendedPublicLibrariesFilePrefix = "public.libraries-";
  5. constexpr const char* kExtendedPublicLibrariesFileSuffix = ".txt";
  6. constexpr const char* kApexLibrariesConfigFile = "/linkerconfig/apex.libraries.config.txt";
  7. constexpr const char* kVendorPublicLibrariesFile = "/vendor/etc/public.libraries.txt";
  8. constexpr const char* kLlndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt";
  9. constexpr const char* kVndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt";
复制代码
只要在命名空间对应的设置文件中加上自己必要的共享库即可
2. native进程

2.1 native 命名空间设置初始化

native进程的so库是直接通过dlopen打开的,而其对应的命名空间也是直接通过linker举行判断的,并没有调用到libnativeloader.so,因此native进程的设置方式也与应用进程不同
2.1.1 android_namespace_t::is_accessible

前一篇Android system — 链接器命名空间(linker namespace)源码分析 介绍了dlopen时会通过is_accessible举行权限判断
  1. // bionic/linker/linker_namespaces.cpp
  2. // Given an absolute path, can this library be loaded into this namespace?
  3. bool android_namespace_t::is_accessible(const std::string& file) {
  4.   //判断命名空间的is_isolated_,即是否为严格隔离,如果不是则权限检查通过。
  5.   if (!is_isolated_) {
  6.     return true;
  7.   }
  8.   //判断是否在允许名单中
  9.   if (!allowed_libs_.empty()) {
  10.     const char *lib_name = basename(file.c_str());
  11.     if (std::find(allowed_libs_.begin(), allowed_libs_.end(), lib_name) == allowed_libs_.end()) {
  12.       return false;
  13.     }
  14.   }
  15.   //判断是否在ld_library_paths中(LD_LIBRARY_PATH设置)
  16.   for (const auto& dir : ld_library_paths_) {
  17.     if (file_is_in_dir(file, dir)) {
  18.       return true;
  19.     }
  20.   }
  21.   //判断是否在default_library_paths中
  22.   for (const auto& dir : default_library_paths_) {
  23.     if (file_is_in_dir(file, dir)) {
  24.       return true;
  25.     }
  26.   }
  27.   //判断是否在特权路径permitted_paths中
  28.   for (const auto& dir : permitted_paths_) {
  29.     if (file_is_under_dir(file, dir)) {
  30.       return true;
  31.     }
  32.   }
  33.   return false;
  34. }
复制代码
我们可以看到这里有个allowed_libs_,我们跟踪代码可以发现linker_namespaces.h中有set_allowed_libs接口
  1. // bionic/linker/linker_namespaces.h
  2.   const std::vector<std::string>& get_allowed_libs() const { return allowed_libs_; }
  3.   void set_allowed_libs(std::vector<std::string>&& allowed_libs) {
  4.     allowed_libs_ = std::move(allowed_libs);
  5.   }
  6.   void set_allowed_libs(const std::vector<std::string>& allowed_libs) {
  7.     allowed_libs_ = allowed_libs;
  8.   }
复制代码
2.1.2 init_default_namespaces

通过这个思路我们发现调用实在在init_default_namespaces


  • 初始化default命名空间
  • 初始化vndk等其他命名空间
  • 在命名空间之间创建链接
  1. std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path) {
  2.   g_default_namespace.set_name("(default)");
  3.   soinfo* somain = solist_get_somain();
  4.   const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
  5.                                                        somain->load_bias);
  6.   const char* bname = (interp != nullptr) ? basename(interp) : nullptr;
  7.   g_is_asan = bname != nullptr &&
  8.               (strcmp(bname, "linker_asan") == 0 ||
  9.                strcmp(bname, "linker_asan64") == 0);
  10.   const Config* config = nullptr;
  11.   {
  12.     std::string ld_config_file_path = get_ld_config_file_path(executable_path);
  13.     INFO("[ Reading linker config "%s" ]", ld_config_file_path.c_str());
  14.     ScopedTrace trace(("linker config " + ld_config_file_path).c_str());
  15.     std::string error_msg;
  16.     if (!Config::read_binary_config(ld_config_file_path.c_str(), executable_path, g_is_asan,
  17.                                     &config, &error_msg)) {
  18.       if (!error_msg.empty()) {
  19.         DL_WARN("Warning: couldn't read '%s' for '%s' (using default configuration instead): %s",
  20.                 ld_config_file_path.c_str(), executable_path, error_msg.c_str());
  21.       }
  22.       config = nullptr;
  23.     }
  24.   }
  25.   if (config == nullptr) {
  26.     return init_default_namespace_no_config(g_is_asan);
  27.   }
  28.   const auto& namespace_configs = config->namespace_configs();
  29.   std::unordered_map<std::string, android_namespace_t*> namespaces;
  30.   // 1. Initialize default namespace
  31.   const NamespaceConfig* default_ns_config = config->default_namespace_config();
  32.   g_default_namespace.set_isolated(default_ns_config->isolated());
  33.   g_default_namespace.set_default_library_paths(default_ns_config->search_paths());
  34.   g_default_namespace.set_permitted_paths(default_ns_config->permitted_paths());
  35.   namespaces[default_ns_config->name()] = &g_default_namespace;
  36.   if (default_ns_config->visible()) {
  37.     g_exported_namespaces[default_ns_config->name()] = &g_default_namespace;
  38.   }
  39.   // 2. Initialize other namespaces
  40.   for (auto& ns_config : namespace_configs) {
  41.     if (namespaces.find(ns_config->name()) != namespaces.end()) {
  42.       continue;
  43.     }
  44.     android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
  45.     ns->set_name(ns_config->name());
  46.     ns->set_isolated(ns_config->isolated());
  47.     ns->set_default_library_paths(ns_config->search_paths());
  48.     ns->set_permitted_paths(ns_config->permitted_paths());
  49.     ns->set_allowed_libs(ns_config->allowed_libs());
  50.     namespaces[ns_config->name()] = ns;
  51.     if (ns_config->visible()) {
  52.       g_exported_namespaces[ns_config->name()] = ns;
  53.     }
  54.   }
  55.   // 3. Establish links between namespaces
  56.   for (auto& ns_config : namespace_configs) {
  57.     auto it_from = namespaces.find(ns_config->name());
  58.     CHECK(it_from != namespaces.end());
  59.     android_namespace_t* namespace_from = it_from->second;
  60.     for (const NamespaceLinkConfig& ns_link : ns_config->links()) {
  61.       auto it_to = namespaces.find(ns_link.ns_name());
  62.       CHECK(it_to != namespaces.end());
  63.       android_namespace_t* namespace_to = it_to->second;
  64.       if (ns_link.allow_all_shared_libs()) {
  65.         link_namespaces_all_libs(namespace_from, namespace_to);
  66.       } else {
  67.         link_namespaces(namespace_from, namespace_to, ns_link.shared_libs().c_str());
  68.       }
  69.     }
  70.   }
  71.   // we can no longer rely on the fact that libdl.so is part of default namespace
  72.   // this is why we want to add ld-android.so to all namespaces from ld.config.txt
  73.   soinfo* ld_android_so = solist_get_head();
  74.   // we also need vdso to be available for all namespaces (if present)
  75.   soinfo* vdso = solist_get_vdso();
  76.   for (auto it : namespaces) {
  77.     if (it.second != &g_default_namespace) {
  78.       it.second->add_soinfo(ld_android_so);
  79.       if (vdso != nullptr) {
  80.         it.second->add_soinfo(vdso);
  81.       }
  82.       // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
  83.     }
  84.   }
  85.   set_application_target_sdk_version(config->target_sdk_version());
  86.   std::vector<android_namespace_t*> created_namespaces;
  87.   created_namespaces.reserve(namespaces.size());
  88.   for (const auto& kv : namespaces) {
  89.     created_namespaces.push_back(kv.second);
  90.   }
  91.   return created_namespaces;
  92. }
  93. }
复制代码
这内里我们发现设置文件是通过读取设置文件举行设置的,设置文件ld_config_file_path在Android 11后便改为/linkerconfig/ld.config.txt
  1. static const char* const kLdConfigArchFilePath = "/system/etc/ld.config." ABI_STRING ".txt";
  2. static const char* const kLdConfigFilePath = "/system/etc/ld.config.txt";
  3. static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
  4. static const char* const kLdGeneratedConfigFilePath = "/linkerconfig/ld.config.txt";
  5. static std::string get_ld_config_file_path(const char* executable_path) {
  6. #ifdef USE_LD_CONFIG_FILE
  7.   // This is a debugging/testing only feature. Must not be available on
  8.   // production builds.
  9.   const char* ld_config_file_env = getenv("LD_CONFIG_FILE");
  10.   if (ld_config_file_env != nullptr && file_exists(ld_config_file_env)) {
  11.     return ld_config_file_env;
  12.   }
  13. #endif
  14.   std::string path = get_ld_config_file_apex_path(executable_path);
  15.   if (!path.empty()) {
  16.     if (file_exists(path.c_str())) {
  17.       return path;
  18.     }
  19.     DL_WARN("Warning: couldn't read config file "%s" for "%s"",
  20.             path.c_str(), executable_path);
  21.   }
  22.   path = kLdConfigArchFilePath;
  23.   if (file_exists(path.c_str())) {
  24.     return path;
  25.   }
  26.   if (file_exists(kLdGeneratedConfigFilePath)) {
  27.     return kLdGeneratedConfigFilePath;
  28.   }
  29.   if (is_linker_config_expected(executable_path)) {
  30.     DL_WARN("Warning: failed to find generated linker configuration from "%s"",
  31.             kLdGeneratedConfigFilePath);
  32.   }
  33.   path = get_ld_config_file_vndk_path();
  34.   if (file_exists(path.c_str())) {
  35.     return path;
  36.   }
  37.   return kLdConfigFilePath;
  38. }
复制代码
2.2 设置共享库位置

上一章我们提到了设置文件位置为/linkerconfig/ld.config.txt,
在Android 11以前ld.config.txt是通过静态文件设置的,而Android 11是改为linkerconfig动态生成
我们以一个vendor/bin下的native 步伐为例,要利用system/lib下的库
在Android system — Android链接器命名空间(Android 11后)中,我们提到了“目录-区段”映射属性dir.name,指向 [name] 区段所应用到的目录的路径,实在就是baseconfig.cc中定义的dirToSection
  1. // system/linkerconfig/contents/configuration/baseconfig.cc
  2. android::linkerconfig::modules::Configuration CreateBaseConfiguration(
  3.     Context& ctx) {
  4.   std::vector<Section> sections;
  5.   ctx.SetCurrentLinkerConfigType(LinkerConfigType::Default);
  6.   // Don't change the order here. The first pattern that matches with the
  7.   // absolute path of an executable is selected.
  8.   std::vector<DirToSection> dirToSection = {
  9.       {"/system/bin/", "system"},
  10.       {"/system/xbin/", "system"},
  11.       {Var("SYSTEM_EXT") + "/bin/", "system"},
  12.       // Processes from the product partition will have a separate section if
  13.       // PRODUCT_PRODUCT_VNDK_VERSION is defined. Otherwise, they are run from
  14.       // the "system" section.
  15.       {Var("PRODUCT") + "/bin/", "product"},
  16.       {"/odm/bin/", "vendor"},
  17.       {"/vendor/bin/", "vendor"},
  18.       {"/data/nativetest/odm", "vendor"},
  19.       {"/data/nativetest64/odm", "vendor"},
  20.       {"/data/benchmarktest/odm", "vendor"},
  21.       {"/data/benchmarktest64/odm", "vendor"},
  22.       {"/data/nativetest/vendor", "vendor"},
  23.       {"/data/nativetest64/vendor", "vendor"},
  24.       {"/data/benchmarktest/vendor", "vendor"},
  25.       {"/data/benchmarktest64/vendor", "vendor"},
  26.       {"/data/nativetest/unrestricted", "unrestricted"},
  27.       {"/data/nativetest64/unrestricted", "unrestricted"},
  28.       // Create isolated namespace for development purpose.
  29.       // This isolates binary from the system so binaries and libraries from
  30.       // this location can be separated from system libraries.
  31.       {"/data/local/tmp/isolated", "isolated"},
  32.       // Create directories under shell-writable /data/local/tests for
  33.       // each namespace in order to run tests.
  34.       {"/data/local/tests/product", "product"},
  35.       {"/data/local/tests/system", "system"},
  36.       {"/data/local/tests/unrestricted", "unrestricted"},
  37.       {"/data/local/tests/vendor", "vendor"},
  38.       // TODO(b/123864775): Ensure tests are run from one of the subdirectories
  39.       // above.  Then clean this up.
  40.       {"/data/local/tmp", "unrestricted"},
  41.       {"/postinstall", "postinstall"},
  42.       // Fallback entry to provide APEX namespace lookups for binaries anywhere
  43.       // else. This must be last.
  44.       {"/data", "system"},
  45.       // TODO(b/168556887): Remove this when we have a dedicated section for
  46.       // binaries in APKs
  47.       {Var("PRODUCT") + "/app/", "system"},
  48.   };
  49.   sections.emplace_back(BuildSystemSection(ctx));
  50.   if (ctx.IsVndkAvailable()) {
  51.     sections.emplace_back(BuildVendorSection(ctx));
  52.     if (android::linkerconfig::modules::IsProductVndkVersionDefined()) {
  53.       sections.emplace_back(BuildProductSection(ctx));
  54.     } else {
  55.       RedirectSection(dirToSection, "product", "system");
  56.     }
  57.   } else {
  58.     RemoveSection(dirToSection, "product");
  59.     RemoveSection(dirToSection, "vendor");
  60.   }
  61.   sections.emplace_back(BuildUnrestrictedSection(ctx));
  62.   sections.emplace_back(BuildPostInstallSection(ctx));
  63.   sections.emplace_back(BuildIsolatedSection(ctx));
  64.   return android::linkerconfig::modules::Configuration(std::move(sections),
  65.                                                        dirToSection);
  66. }
复制代码
由于我们是vendor/bin下面的步伐,以是可以看出来我们是vendor section,因此我们看BuildVendorSection即可。
  1. // system/linkerconfig/contents/section/vendor.cc
  2. Section BuildVendorSection(Context& ctx) {
  3.   ctx.SetCurrentSection(SectionType::Vendor);
  4.   std::vector<Namespace> namespaces;
  5.   namespaces.emplace_back(BuildVendorDefaultNamespace(ctx));
  6.   namespaces.emplace_back(BuildVndkNamespace(ctx, VndkUserPartition::Vendor));
  7.   namespaces.emplace_back(BuildSystemNamespace(ctx));
  8.   namespaces.emplace_back(BuildRsNamespace(ctx));
  9.   if (android::linkerconfig::modules::IsVndkInSystemNamespace()) {
  10.     namespaces.emplace_back(BuildVndkInSystemNamespace(ctx));
  11.   }
  12.   std::set<std::string> visible_apexes;
  13.   // APEXes with public libs should be visible
  14.   for (const auto& apex : ctx.GetApexModules()) {
  15.     if (apex.public_libs.size() > 0) {
  16.       visible_apexes.insert(apex.name);
  17.     }
  18.   }
  19.   android::linkerconfig::modules::LibProviders libs_providers = {};
  20.   if (ctx.IsVndkAvailable()) {
  21.     libs_providers[":vndk"] = android::linkerconfig::modules::LibProvider{
  22.         "vndk",
  23.         std::bind(BuildVndkNamespace, ctx, VndkUserPartition::Vendor),
  24.         {Var("VNDK_SAMEPROCESS_LIBRARIES_VENDOR"),
  25.          Var("VNDK_CORE_LIBRARIES_VENDOR")},
  26.     };
  27.   }
  28.   return BuildSection(
  29.       ctx, "vendor", std::move(namespaces), visible_apexes, libs_providers);
  30. }
复制代码
我们可以看到末了调用了BuildSection,在此中调用了AddStandardSystemLinks 添加system的共享库
  1. // system/linkerconfig/contents/section/sectionbuilder.cc
  2. Section BuildSection(const Context& ctx, const std::string& name,
  3.                      std::vector<Namespace>&& namespaces,
  4.                      const std::set<std::string>& visible_apexes,
  5.                      const LibProviders& providers) {
  6.   // add additional visible APEX namespaces
  7.   for (const auto& apex : ctx.GetApexModules()) {
  8.     if (visible_apexes.find(apex.name) == visible_apexes.end() &&
  9.         !apex.visible) {
  10.       continue;
  11.     }
  12.     if (auto it = std::find_if(
  13.             namespaces.begin(),
  14.             namespaces.end(),
  15.             [&apex](auto& ns) { return ns.GetName() == apex.namespace_name; });
  16.         it == namespaces.end()) {
  17.       auto ns = ctx.BuildApexNamespace(apex, true);
  18.       namespaces.push_back(std::move(ns));
  19.     } else {
  20.       // override "visible" when the apex is already created
  21.       it->SetVisible(true);
  22.     }
  23.   }
  24.   // resolve provide/require constraints
  25.   Section section(std::move(name), std::move(namespaces));
  26.   if (auto res = section.Resolve(ctx, providers); !res.ok()) {
  27.     LOG(ERROR) << res.error();
  28.   }
  29.   AddStandardSystemLinks(ctx, &section); // 添加通用的system link共享库
  30.   return section;
  31. }
复制代码
在kBionicLibs 加上我们必要的库即可
  1. // system/linkerconfig/contents/common/system_links.cc
  2. namespace {
  3. const std::vector<std::string> kBionicLibs = {
  4.     "libc.so",
  5.     "libdl.so",
  6.     "libdl_android.so",
  7.     "libm.so",
  8. };
  9. }  // namespace
  10. namespace android {
  11. namespace linkerconfig {
  12. namespace contents {
  13. using android::linkerconfig::modules::Namespace;
  14. using android::linkerconfig::modules::Section;
  15. void AddStandardSystemLinks(const Context& ctx, Section* section) {
  16.   const bool debuggable = android::base::GetBoolProperty("ro.debuggable", false);
  17.   const std::string system_ns_name = ctx.GetSystemNamespaceName();
  18.   const bool is_section_vndk_enabled = ctx.IsSectionVndkEnabled();
  19.   section->ForEachNamespaces([&](Namespace& ns) {
  20.     if (ns.GetName() != system_ns_name) {
  21.       ns.GetLink(system_ns_name).AddSharedLib(kBionicLibs);
  22.       if (!is_section_vndk_enabled || ns.GetName() != "default") {
  23.         // TODO(b/185199923) remove the default value
  24.         ns.GetLink(system_ns_name)
  25.             .AddSharedLib(Var("SANITIZER_RUNTIME_LIBRARIES", ""));
  26.       }
  27.       if (debuggable) {
  28.         // Library on the system image that can be dlopened for debugging purposes.
  29.         ns.GetLink(system_ns_name).AddSharedLib("libfdtrack.so");
  30.       }
  31.     }
  32.   });
  33. }
  34. }  // namespace contents
  35. }  // namespace linkerconfig
  36. }  // namespace android
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表