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