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