Android system — 链接器命名空间共享库配置方法(Android 11后),Android 11后系统链接器命名空间共享库配置方法指南

马肤

温馨提示:这篇文章已超过368天没有更新,请注意相关的内容是否还可用!

摘要:本文介绍了Android系统(Android 11及以后版本)中链接器命名空间共享库的配置方法。文章详细阐述了如何配置共享库,以便在应用程序中使用。通过优化配置,可以提高系统的运行效率和应用程序的性能。本文旨在为开发者提供关于Android系统链接器命名空间共享库配置的有效指南。

Android system — 链接器命名空间共享库配置方法

  • 1. 应用进程
    • 1.1 应用进程类加载器的命名空间初始化
      • 1.1.1 OpenNativeLibrary
      • 1.1.2 LibraryNamespaces::Create
      • 1.2 配置共享库位置
      • 2. native进程
        • 2.1 native 命名空间配置初始化
          • 2.1.1 android_namespace_t::is_accessible
          • 2.1.2 init_default_namespaces
          • 2.2 配置共享库位置

            1. 应用进程

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

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

            Android system — 链接器命名空间共享库配置方法(Android 11后),Android 11后系统链接器命名空间共享库配置方法指南 第1张
            (图片来源网络,侵删)

            1.1.1 OpenNativeLibrary

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

            • OpenNativeLibrary先判断classloader类加载器是否为空,如果为空直接调用android_dlopen_ext加载库文件
            • 如果判断classloader类加载器不为空,并且classloader类加载器没有对应的命名空间(第一次调用System.loadLibrary)就调用LibraryNamespaces::Create创建新的命名空间。
              void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
                                      jobject class_loader, const char* caller_location, jstring library_path,
                                      bool* needs_native_bridge, char** error_msg) {
              #if defined(ART_TARGET_ANDROID)
                UNUSED(target_sdk_version);
                if (class_loader == nullptr) { //如果类加载器为空直接调用android_dlopen_ext加载库文件
                  *needs_native_bridge = false;
                  if (caller_location != nullptr) {
                    android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
                    if (boot_namespace != nullptr) {
                      const android_dlextinfo dlextinfo = {
                          .flags = ANDROID_DLEXT_USE_NAMESPACE,
                          .library_namespace = boot_namespace,
                      };
                      void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
                      if (handle == nullptr) {
                        *error_msg = strdup(dlerror());
                      }
                      return handle;
                    }
                  }
                  // Check if the library is in NATIVELOADER_DEFAULT_NAMESPACE_LIBS and should
                  // be loaded from the kNativeloaderExtraLibs namespace.
                  {
                    Result handle = TryLoadNativeloaderExtraLib(path);
                    if (!handle.ok()) {
                      *error_msg = strdup(handle.error().message().c_str());
                      return nullptr;
                    }
                    if (handle.value() != nullptr) {
                      return handle.value();
                    }
                  }
                  // Fall back to the system namespace. This happens for preloaded JNI
                  // libraries in the zygote.
                  // TODO(b/185833744): Investigate if this should fall back to the app main
                  // namespace (aka anonymous namespace) instead.
                  void* handle = OpenSystemLibrary(path, RTLD_NOW);
                  if (handle == nullptr) {
                    *error_msg = strdup(dlerror());
                  }
                  return handle;
                }
                std::lock_guard guard(g_namespaces_mutex);
                NativeLoaderNamespace* ns;
                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.
                  Result isolated_ns =
                      CreateClassLoaderNamespaceLocked(env,
                                                       target_sdk_version,
                                                       class_loader,
                                                       /*is_shared=*/false,
                                                       /*dex_path=*/nullptr,
                                                       library_path,
                                                       /*permitted_path=*/nullptr,
                                                       /*uses_library_list=*/nullptr);
                  if (!isolated_ns.ok()) {
                    *error_msg = strdup(isolated_ns.error().message().c_str());
                    return nullptr;
                  } else {
                    ns = *isolated_ns;
                  }
                }
                return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
              

              在CreateClassLoaderNamespaceLocked中我们可以看到调用了LibraryNamespaces::Create创建新的命名空间

              Android system — 链接器命名空间共享库配置方法(Android 11后),Android 11后系统链接器命名空间共享库配置方法指南 第2张
              (图片来源网络,侵删)
              Result CreateClassLoaderNamespaceLocked(JNIEnv* env,
                               int32_t target_sdk_version,
                               jobject class_loader,
                               bool is_shared,
                               jstring dex_path,
                               jstring library_path,
                               jstring permitted_path,
                               jstring uses_library_list)
                  REQUIRES(g_namespaces_mutex) {
                Result ns = g_namespaces->Create(env,
                          target_sdk_version,
                          class_loader,
                          is_shared,
                          dex_path,
                          library_path,
                          permitted_path,
                          uses_library_list);
                if (!ns.ok()) {
                  return ns;
                }
                Result linked = CreateNativeloaderDefaultNamespaceLibsLink(*ns.value());
                if (!linked.ok()) {
                  return linked.error();
                }
                return ns;
              }
              

              1.1.2 LibraryNamespaces::Create

              • 先调用android_create_namespace创建一个clns命名空间
              • 调用android_linker_namespace设置新创建的命名空间链接到system、APEX和vendor等命名空间
              • 设置链接到system、APEX等命名空间的共享库
                Result LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
                          jobject class_loader, bool is_shared,
                          jstring dex_path_j,
                          jstring java_library_path,
                          jstring java_permitted_path,
                          jstring uses_library_list) {
                  std::string library_path;  // empty string by default.
                  std::string dex_path;
                  ......
                  // Create the app namespace
                  NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
                  // Heuristic: the first classloader with non-empty library_path is assumed to
                  // be the main classloader for app
                  // TODO(b/139178525) remove this heuristic by determining this in LoadedApk (or its
                  // friends) and then passing it down to here.
                  bool is_main_classloader = app_main_namespace_ == nullptr && !library_path.empty();
                  // Policy: the namespace for the main classloader is also used as the
                  // anonymous namespace.
                  bool also_used_as_anonymous = is_main_classloader;
                  // Note: this function is executed with g_namespaces_mutex held, thus no
                  // racing here.
                  //创建命名空间,namespace_name为kClassloaderNamespaceName = "clns"
                  auto app_ns = NativeLoaderNamespace::Create(
                      namespace_name, library_path, permitted_path, parent_ns, is_shared,
                      target_sdk_version IsBridged();
                  auto system_ns = NativeLoaderNamespace::GetSystemNamespace(is_bridged);
                  if (!system_ns.ok()) {
                    return system_ns.error();
                  }
                  // 新创建的命名空间链接到system,共享库设置为system_exposed_libraries
                  auto linked = app_ns->Link(&system_ns.value(), system_exposed_libraries);
                  if (!linked.ok()) {
                    return linked.error();
                  }
                  for (const auto&[apex_ns_name, public_libs] : apex_public_libraries()) {
                    auto ns = NativeLoaderNamespace::GetExportedNamespace(apex_ns_name, is_bridged);
                    // Even if APEX namespace is visible, it may not be available to bridged.
                    if (ns.ok()) {
                      // 新创建的命名空间链接到APEX,共享库设置为public_libs
                      linked = app_ns->Link(&ns.value(), public_libs);
                      if (!linked.ok()) {
                        return linked.error();
                      }
                    }
                  }
                  // Give access to VNDK-SP libraries from the 'vndk' namespace for unbundled vendor apps.
                  if (unbundled_app_origin == APK_ORIGIN_VENDOR && !vndksp_libraries_vendor().empty()) {
                    auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
                    if (vndk_ns.ok()) {
                      // 新创建的命名空间链接到vndk,共享库设置为vndksp_libraries_vendor()
                      linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_vendor());
                      if (!linked.ok()) {
                        return linked.error();
                      }
                    }
                  }
                  // Give access to VNDK-SP libraries from the 'vndk_product' namespace for unbundled product apps.
                  if (unbundled_app_origin == APK_ORIGIN_PRODUCT && !vndksp_libraries_product().empty()) {
                    auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkProductNamespaceName, is_bridged);
                    if (vndk_ns.ok()) {
                      linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_product());
                      if (!linked.ok()) {
                        return linked.error();
                      }
                    }
                  }
                  for (const std::string& each_jar_path : android::base::Split(dex_path, ":")) {
                    auto apex_ns_name = FindApexNamespaceName(each_jar_path);
                    if (apex_ns_name.ok()) {
                      const auto& jni_libs = apex_jni_libraries(*apex_ns_name);
                      if (jni_libs != "") {
                        auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged);
                        if (apex_ns.ok()) {
                          linked = app_ns->Link(&apex_ns.value(), jni_libs);
                          if (!linked.ok()) {
                            return linked.error();
                          }
                        }
                      }
                    }
                  }
                  auto vendor_libs = filter_public_libraries(target_sdk_version, uses_libraries,
                                                             vendor_public_libraries());
                  if (!vendor_libs.empty()) {
                    auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
                    // when vendor_ns is not configured, link to the system namespace
                    auto target_ns = vendor_ns.ok() ? vendor_ns : system_ns;
                    if (target_ns.ok()) {
                      linked = app_ns->Link(&target_ns.value(), vendor_libs);
                      if (!linked.ok()) {
                        return linked.error();
                      }
                    }
                  }
                  auto product_libs = filter_public_libraries(target_sdk_version, uses_libraries,
                                                              product_public_libraries());
                  if (!product_libs.empty()) {
                    auto target_ns = system_ns;
                    if (is_product_vndk_version_defined()) {
                      // If ro.product.vndk.version is defined, product namespace provides the product libraries.
                      target_ns = NativeLoaderNamespace::GetExportedNamespace(kProductNamespaceName, is_bridged);
                    }
                    if (target_ns.ok()) {
                      linked = app_ns->Link(&target_ns.value(), product_libs);
                      if (!linked.ok()) {
                        return linked.error();
                      }
                    } else {
                      // The linkerconfig must have a problem on defining the product namespace in the system
                      // section. Skip linking product namespace. This will not affect most of the apps. Only the
                      // apps that requires the product public libraries will fail.
                      ALOGW("Namespace for product libs not found: %s", target_ns.error().message().c_str());
                    }
                  }
                  auto& emplaced = namespaces_.emplace_back(
                      std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
                  if (is_main_classloader) {
                    app_main_namespace_ = &emplaced.second;
                  }
                  return &emplaced.second;
                }
                

                1.2 配置共享库位置

                通过上面的代码跟踪我们会发现,其实在Android 11后,应用进程共享库的配置位置都在public_libraries.cpp中

                // art/libnativeloader/public_libraries.cpp
                namespace {
                constexpr const char* kDefaultPublicLibrariesFile = "/etc/public.libraries.txt";
                constexpr const char* kExtendedPublicLibrariesFilePrefix = "public.libraries-";
                constexpr const char* kExtendedPublicLibrariesFileSuffix = ".txt";
                constexpr const char* kApexLibrariesConfigFile = "/linkerconfig/apex.libraries.config.txt";
                constexpr const char* kVendorPublicLibrariesFile = "/vendor/etc/public.libraries.txt";
                constexpr const char* kLlndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt";
                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进行权限判断

                // bionic/linker/linker_namespaces.cpp
                // Given an absolute path, can this library be loaded into this namespace?
                bool android_namespace_t::is_accessible(const std::string& file) {
                  //判断命名空间的is_isolated_,即是否为严格隔离,如果不是则权限检查通过。
                  if (!is_isolated_) {
                    return true;
                  }
                  //判断是否在允许名单中
                  if (!allowed_libs_.empty()) {
                    const char *lib_name = basename(file.c_str());
                    if (std::find(allowed_libs_.begin(), allowed_libs_.end(), lib_name) == allowed_libs_.end()) {
                      return false;
                    }
                  }
                  //判断是否在ld_library_paths中(LD_LIBRARY_PATH设置)
                  for (const auto& dir : ld_library_paths_) {
                    if (file_is_in_dir(file, dir)) {
                      return true;
                    }
                  }
                  //判断是否在default_library_paths中
                  for (const auto& dir : default_library_paths_) {
                    if (file_is_in_dir(file, dir)) {
                      return true;
                    }
                  }
                  //判断是否在特权路径permitted_paths中
                  for (const auto& dir : permitted_paths_) {
                    if (file_is_under_dir(file, dir)) {
                      return true;
                    }
                  }
                  return false;
                }
                

                我们可以看到这里有个allowed_libs_,我们跟踪代码可以发现linker_namespaces.h中有set_allowed_libs接口

                // bionic/linker/linker_namespaces.h 
                  const std::vector& get_allowed_libs() const { return allowed_libs_; }
                  void set_allowed_libs(std::vector&& allowed_libs) {
                    allowed_libs_ = std::move(allowed_libs);
                  }
                  void set_allowed_libs(const std::vector& allowed_libs) {
                    allowed_libs_ = allowed_libs;
                  }
                

                2.1.2 init_default_namespaces

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

                • 初始化default命名空间
                • 初始化vndk等其他命名空间
                • 在命名空间之间建立链接
                  std::vector init_default_namespaces(const char* executable_path) {
                    g_default_namespace.set_name("(default)");
                    soinfo* somain = solist_get_somain();
                    const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
                          somain->load_bias);
                    const char* bname = (interp != nullptr) ? basename(interp) : nullptr;
                    g_is_asan = bname != nullptr &&
                                (strcmp(bname, "linker_asan") == 0 ||
                                 strcmp(bname, "linker_asan64") == 0);
                    const Config* config = nullptr;
                    {
                      std::string ld_config_file_path = get_ld_config_file_path(executable_path);
                      INFO("[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
                      ScopedTrace trace(("linker config " + ld_config_file_path).c_str());
                      std::string error_msg;
                      if (!Config::read_binary_config(ld_config_file_path.c_str(), executable_path, g_is_asan,
                                                      &config, &error_msg)) {
                        if (!error_msg.empty()) {
                          DL_WARN("Warning: couldn't read '%s' for '%s' (using default configuration instead): %s",
                                  ld_config_file_path.c_str(), executable_path, error_msg.c_str());
                        }
                        config = nullptr;
                      }
                    }
                    if (config == nullptr) {
                      return init_default_namespace_no_config(g_is_asan);
                    }
                    const auto& namespace_configs = config->namespace_configs();
                    std::unordered_map namespaces;
                    // 1. Initialize default namespace
                    const NamespaceConfig* default_ns_config = config->default_namespace_config();
                    g_default_namespace.set_isolated(default_ns_config->isolated());
                    g_default_namespace.set_default_library_paths(default_ns_config->search_paths());
                    g_default_namespace.set_permitted_paths(default_ns_config->permitted_paths());
                    namespaces[default_ns_config->name()] = &g_default_namespace;
                    if (default_ns_config->visible()) {
                      g_exported_namespaces[default_ns_config->name()] = &g_default_namespace;
                    }
                    // 2. Initialize other namespaces
                    for (auto& ns_config : namespace_configs) {
                      if (namespaces.find(ns_config->name()) != namespaces.end()) {
                        continue;
                      }
                      android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
                      ns->set_name(ns_config->name());
                      ns->set_isolated(ns_config->isolated());
                      ns->set_default_library_paths(ns_config->search_paths());
                      ns->set_permitted_paths(ns_config->permitted_paths());
                      ns->set_allowed_libs(ns_config->allowed_libs());
                      namespaces[ns_config->name()] = ns;
                      if (ns_config->visible()) {
                        g_exported_namespaces[ns_config->name()] = ns;
                      }
                    }
                    // 3. Establish links between namespaces
                    for (auto& ns_config : namespace_configs) {
                      auto it_from = namespaces.find(ns_config->name());
                      CHECK(it_from != namespaces.end());
                      android_namespace_t* namespace_from = it_from->second;
                      for (const NamespaceLinkConfig& ns_link : ns_config->links()) {
                        auto it_to = namespaces.find(ns_link.ns_name());
                        CHECK(it_to != namespaces.end());
                        android_namespace_t* namespace_to = it_to->second;
                        if (ns_link.allow_all_shared_libs()) {
                          link_namespaces_all_libs(namespace_from, namespace_to);
                        } else {
                          link_namespaces(namespace_from, namespace_to, ns_link.shared_libs().c_str());
                        }
                      }
                    }
                    // we can no longer rely on the fact that libdl.so is part of default namespace
                    // this is why we want to add ld-android.so to all namespaces from ld.config.txt
                    soinfo* ld_android_so = solist_get_head();
                    // we also need vdso to be available for all namespaces (if present)
                    soinfo* vdso = solist_get_vdso();
                    for (auto it : namespaces) {
                      if (it.second != &g_default_namespace) {
                        it.second->add_soinfo(ld_android_so);
                        if (vdso != nullptr) {
                          it.second->add_soinfo(vdso);
                        }
                        // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
                      }
                    }
                    set_application_target_sdk_version(config->target_sdk_version());
                    std::vector created_namespaces;
                    created_namespaces.reserve(namespaces.size());
                    for (const auto& kv : namespaces) {
                      created_namespaces.push_back(kv.second);
                    }
                    return created_namespaces;
                  }
                  }
                  

                  这里面我们发现配置文件是通过读取配置文件进行配置的,配置文件ld_config_file_path在Android 11后便改为/linkerconfig/ld.config.txt

                  static const char* const kLdConfigArchFilePath = "/system/etc/ld.config." ABI_STRING ".txt";
                  static const char* const kLdConfigFilePath = "/system/etc/ld.config.txt";
                  static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
                  static const char* const kLdGeneratedConfigFilePath = "/linkerconfig/ld.config.txt";
                  static std::string get_ld_config_file_path(const char* executable_path) {
                  #ifdef USE_LD_CONFIG_FILE
                    // This is a debugging/testing only feature. Must not be available on
                    // production builds.
                    const char* ld_config_file_env = getenv("LD_CONFIG_FILE");
                    if (ld_config_file_env != nullptr && file_exists(ld_config_file_env)) {
                      return ld_config_file_env;
                    }
                  #endif
                    std::string path = get_ld_config_file_apex_path(executable_path);
                    if (!path.empty()) {
                      if (file_exists(path.c_str())) {
                        return path;
                      }
                      DL_WARN("Warning: couldn't read config file \"%s\" for \"%s\"",
                              path.c_str(), executable_path);
                    }
                    path = kLdConfigArchFilePath;
                    if (file_exists(path.c_str())) {
                      return path;
                    }
                    if (file_exists(kLdGeneratedConfigFilePath)) {
                      return kLdGeneratedConfigFilePath;
                    }
                    if (is_linker_config_expected(executable_path)) {
                      DL_WARN("Warning: failed to find generated linker configuration from \"%s\"",
                              kLdGeneratedConfigFilePath);
                    }
                    path = get_ld_config_file_vndk_path();
                    if (file_exists(path.c_str())) {
                      return path;
                    }
                    return kLdConfigFilePath;
                  }
                  

                  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

                  // system/linkerconfig/contents/configuration/baseconfig.cc
                  android::linkerconfig::modules::Configuration CreateBaseConfiguration(
                      Context& ctx) {
                    std::vector sections;
                    ctx.SetCurrentLinkerConfigType(LinkerConfigType::Default);
                    // Don't change the order here. The first pattern that matches with the
                    // absolute path of an executable is selected.
                    std::vector dirToSection = {
                        {"/system/bin/", "system"},
                        {"/system/xbin/", "system"},
                        {Var("SYSTEM_EXT") + "/bin/", "system"},
                        // Processes from the product partition will have a separate section if
                        // PRODUCT_PRODUCT_VNDK_VERSION is defined. Otherwise, they are run from
                        // the "system" section.
                        {Var("PRODUCT") + "/bin/", "product"},
                        {"/odm/bin/", "vendor"},
                        {"/vendor/bin/", "vendor"},
                        {"/data/nativetest/odm", "vendor"},
                        {"/data/nativetest64/odm", "vendor"},
                        {"/data/benchmarktest/odm", "vendor"},
                        {"/data/benchmarktest64/odm", "vendor"},
                        {"/data/nativetest/vendor", "vendor"},
                        {"/data/nativetest64/vendor", "vendor"},
                        {"/data/benchmarktest/vendor", "vendor"},
                        {"/data/benchmarktest64/vendor", "vendor"},
                        {"/data/nativetest/unrestricted", "unrestricted"},
                        {"/data/nativetest64/unrestricted", "unrestricted"},
                        // Create isolated namespace for development purpose.
                        // This isolates binary from the system so binaries and libraries from
                        // this location can be separated from system libraries.
                        {"/data/local/tmp/isolated", "isolated"},
                        // Create directories under shell-writable /data/local/tests for
                        // each namespace in order to run tests.
                        {"/data/local/tests/product", "product"},
                        {"/data/local/tests/system", "system"},
                        {"/data/local/tests/unrestricted", "unrestricted"},
                        {"/data/local/tests/vendor", "vendor"},
                        // TODO(b/123864775): Ensure tests are run from one of the subdirectories
                        // above.  Then clean this up.
                        {"/data/local/tmp", "unrestricted"},
                        {"/postinstall", "postinstall"},
                        // Fallback entry to provide APEX namespace lookups for binaries anywhere
                        // else. This must be last.
                        {"/data", "system"},
                        // TODO(b/168556887): Remove this when we have a dedicated section for
                        // binaries in APKs
                        {Var("PRODUCT") + "/app/", "system"},
                    };
                    sections.emplace_back(BuildSystemSection(ctx));
                    if (ctx.IsVndkAvailable()) {
                      sections.emplace_back(BuildVendorSection(ctx));
                      if (android::linkerconfig::modules::IsProductVndkVersionDefined()) {
                        sections.emplace_back(BuildProductSection(ctx));
                      } else {
                        RedirectSection(dirToSection, "product", "system");
                      }
                    } else {
                      RemoveSection(dirToSection, "product");
                      RemoveSection(dirToSection, "vendor");
                    }
                    sections.emplace_back(BuildUnrestrictedSection(ctx));
                    sections.emplace_back(BuildPostInstallSection(ctx));
                    sections.emplace_back(BuildIsolatedSection(ctx));
                    return android::linkerconfig::modules::Configuration(std::move(sections),
                          dirToSection);
                  }
                  

                  因为我们是vendor/bin下面的程序,所以可以看出来我们是vendor section,因此我们看BuildVendorSection即可。

                  // system/linkerconfig/contents/section/vendor.cc
                  Section BuildVendorSection(Context& ctx) {
                    ctx.SetCurrentSection(SectionType::Vendor);
                    std::vector namespaces;
                    namespaces.emplace_back(BuildVendorDefaultNamespace(ctx));
                    namespaces.emplace_back(BuildVndkNamespace(ctx, VndkUserPartition::Vendor));
                    namespaces.emplace_back(BuildSystemNamespace(ctx));
                    namespaces.emplace_back(BuildRsNamespace(ctx));
                    if (android::linkerconfig::modules::IsVndkInSystemNamespace()) {
                      namespaces.emplace_back(BuildVndkInSystemNamespace(ctx));
                    }
                    std::set visible_apexes;
                    // APEXes with public libs should be visible
                    for (const auto& apex : ctx.GetApexModules()) {
                      if (apex.public_libs.size() > 0) {
                        visible_apexes.insert(apex.name);
                      }
                    }
                    android::linkerconfig::modules::LibProviders libs_providers = {};
                    if (ctx.IsVndkAvailable()) {
                      libs_providers[":vndk"] = android::linkerconfig::modules::LibProvider{
                          "vndk",
                          std::bind(BuildVndkNamespace, ctx, VndkUserPartition::Vendor),
                          {Var("VNDK_SAMEPROCESS_LIBRARIES_VENDOR"),
                           Var("VNDK_CORE_LIBRARIES_VENDOR")},
                      };
                    }
                    return BuildSection(
                        ctx, "vendor", std::move(namespaces), visible_apexes, libs_providers);
                  }
                  

                  我们可以看到最后调用了BuildSection,在其中调用了AddStandardSystemLinks 添加system的共享库

                  // system/linkerconfig/contents/section/sectionbuilder.cc
                  Section BuildSection(const Context& ctx, const std::string& name,
                                       std::vector&& namespaces,
                                       const std::set& visible_apexes,
                                       const LibProviders& providers) {
                    // add additional visible APEX namespaces
                    for (const auto& apex : ctx.GetApexModules()) {
                      if (visible_apexes.find(apex.name) == visible_apexes.end() &&
                          !apex.visible) {
                        continue;
                      }
                      if (auto it = std::find_if(
                              namespaces.begin(),
                              namespaces.end(),
                              [&apex](auto& ns) { return ns.GetName() == apex.namespace_name; });
                          it == namespaces.end()) {
                        auto ns = ctx.BuildApexNamespace(apex, true);
                        namespaces.push_back(std::move(ns));
                      } else {
                        // override "visible" when the apex is already created
                        it->SetVisible(true);
                      }
                    }
                    // resolve provide/require constraints
                    Section section(std::move(name), std::move(namespaces));
                    if (auto res = section.Resolve(ctx, providers); !res.ok()) {
                      LOG(ERROR) 
                  const std::vector
                      "libc.so",
                      "libdl.so",
                      "libdl_android.so",
                      "libm.so",
                  };
                  }  // namespace
                  namespace android {
                  namespace linkerconfig {
                  namespace contents {
                  using android::linkerconfig::modules::Namespace;
                  using android::linkerconfig::modules::Section;
                  void AddStandardSystemLinks(const Context& ctx, Section* section) {
                    const bool debuggable = android::base::GetBoolProperty("ro.debuggable", false);
                    const std::string system_ns_name = ctx.GetSystemNamespaceName();
                    const bool is_section_vndk_enabled = ctx.IsSectionVndkEnabled();
                    section-ForEachNamespaces([&](Namespace& ns) {
                      if (ns.GetName() != system_ns_name) {
                        ns.GetLink(system_ns_name).AddSharedLib(kBionicLibs);
                        if (!is_section_vndk_enabled || ns.GetName() != "default") {
                          // TODO(b/185199923) remove the default value
                          ns.GetLink(system_ns_name)
                              .AddSharedLib(Var("SANITIZER_RUNTIME_LIBRARIES", ""));
                        }
                        if (debuggable) {
                          // Library on the system image that can be dlopened for debugging purposes.
                          ns.GetLink(system_ns_name).AddSharedLib("libfdtrack.so");
                        }
                      }
                    });
                  }
                  }  // namespace contents
                  }  // namespace linkerconfig
                  }  // namespace android
                  

0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码