bundle_utils.cc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/android/bundle_utils.h"
  5. #include <android/dlext.h>
  6. #include <dlfcn.h>
  7. #include "base/android/jni_android.h"
  8. #include "base/android/jni_string.h"
  9. #include "base/base_jni_headers/BundleUtils_jni.h"
  10. #include "base/check.h"
  11. #include "base/files/file_path.h"
  12. #include "base/notreached.h"
  13. // These symbols are added by the lld linker when creating a partitioned shared
  14. // library. The symbols live in the base library, and are used to properly load
  15. // the other partitions (feature libraries) when needed.
  16. struct PartitionIndexEntry {
  17. int32_t name_relptr;
  18. int32_t addr_relptr;
  19. uint32_t size;
  20. };
  21. static_assert(sizeof(PartitionIndexEntry) == 12U,
  22. "Unexpected PartitionIndexEntry size");
  23. // Marked as weak_import because these symbols are lld-specific. The method that
  24. // uses them will only be invoked in builds that have lld-generated partitions.
  25. extern PartitionIndexEntry __part_index_begin[] __attribute__((weak_import));
  26. extern PartitionIndexEntry __part_index_end[] __attribute__((weak_import));
  27. extern "C" {
  28. // Marked as weak_import because this symbol is either supplied by the system
  29. // (on Android N+), or by Crazy Linker (Android M and prior).
  30. extern void* android_dlopen_ext(const char* __filename,
  31. int __flags,
  32. const android_dlextinfo* __info)
  33. __attribute__((weak_import));
  34. } // extern "C"
  35. namespace base {
  36. namespace android {
  37. namespace {
  38. const void* ReadRelPtr(const int32_t* relptr) {
  39. return reinterpret_cast<const char*>(relptr) + *relptr;
  40. }
  41. } // namespace
  42. // static
  43. std::string BundleUtils::ResolveLibraryPath(const std::string& library_name,
  44. const std::string& split_name) {
  45. JNIEnv* env = AttachCurrentThread();
  46. ScopedJavaLocalRef<jstring> java_path = Java_BundleUtils_getNativeLibraryPath(
  47. env, ConvertUTF8ToJavaString(env, library_name),
  48. ConvertUTF8ToJavaString(env, split_name));
  49. // TODO(https://crbug.com/1019853): Remove this tolerance.
  50. if (!java_path) {
  51. return std::string();
  52. }
  53. return ConvertJavaStringToUTF8(env, java_path);
  54. }
  55. // static
  56. bool BundleUtils::IsBundle() {
  57. return Java_BundleUtils_isBundleForNative(AttachCurrentThread());
  58. }
  59. // static
  60. void* BundleUtils::DlOpenModuleLibraryPartition(const std::string& library_name,
  61. const std::string& partition,
  62. const std::string& split_name) {
  63. // TODO(https://crbug.com/1019853): Remove this tolerance.
  64. std::string library_path = ResolveLibraryPath(library_name, split_name);
  65. if (library_path.empty()) {
  66. return nullptr;
  67. }
  68. // Linear search is required here because the partition descriptors are not
  69. // ordered. If a large number of partitions come into existence, lld could be
  70. // modified to sort the partitions.
  71. DCHECK(__part_index_begin != nullptr);
  72. DCHECK(__part_index_end != nullptr);
  73. for (const PartitionIndexEntry* part = __part_index_begin;
  74. part != __part_index_end; ++part) {
  75. std::string name(
  76. reinterpret_cast<const char*>(ReadRelPtr(&part->name_relptr)));
  77. if (name == partition) {
  78. android_dlextinfo info = {};
  79. info.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
  80. info.reserved_addr = const_cast<void*>(ReadRelPtr(&part->addr_relptr));
  81. info.reserved_size = part->size;
  82. DCHECK(android_dlopen_ext != nullptr);
  83. return android_dlopen_ext(library_path.c_str(), RTLD_LOCAL, &info);
  84. }
  85. }
  86. NOTREACHED();
  87. return nullptr;
  88. }
  89. } // namespace android
  90. } // namespace base