xref: /aosp_15_r20/art/libnativeloader/public_libraries.cpp (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #define LOG_TAG "nativeloader"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "public_libraries.h"
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include <dirent.h>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include <algorithm>
24*795d594fSAndroid Build Coastguard Worker #include <map>
25*795d594fSAndroid Build Coastguard Worker #include <memory>
26*795d594fSAndroid Build Coastguard Worker #include <regex>
27*795d594fSAndroid Build Coastguard Worker #include <string>
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker #include <android-base/file.h>
30*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
31*795d594fSAndroid Build Coastguard Worker #include <android-base/properties.h>
32*795d594fSAndroid Build Coastguard Worker #include <android-base/result.h>
33*795d594fSAndroid Build Coastguard Worker #include <android-base/strings.h>
34*795d594fSAndroid Build Coastguard Worker #include <log/log.h>
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
37*795d594fSAndroid Build Coastguard Worker #include <android-modules-utils/sdk_level.h>
38*795d594fSAndroid Build Coastguard Worker #include <android/sysprop/VndkProperties.sysprop.h>
39*795d594fSAndroid Build Coastguard Worker #endif
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker #include "utils.h"
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker namespace android::nativeloader {
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker using android::base::ErrnoError;
46*795d594fSAndroid Build Coastguard Worker using android::base::Result;
47*795d594fSAndroid Build Coastguard Worker using internal::ConfigEntry;
48*795d594fSAndroid Build Coastguard Worker using internal::ParseConfig;
49*795d594fSAndroid Build Coastguard Worker using internal::ParseApexLibrariesConfig;
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker namespace {
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker constexpr const char* kDefaultPublicLibrariesFile = "/etc/public.libraries.txt";
54*795d594fSAndroid Build Coastguard Worker constexpr const char* kExtendedPublicLibrariesFilePrefix = "public.libraries-";
55*795d594fSAndroid Build Coastguard Worker constexpr const char* kExtendedPublicLibrariesFileSuffix = ".txt";
56*795d594fSAndroid Build Coastguard Worker constexpr const char* kApexLibrariesConfigFile = "/linkerconfig/apex.libraries.config.txt";
57*795d594fSAndroid Build Coastguard Worker constexpr const char* kVendorPublicLibrariesFile = "/vendor/etc/public.libraries.txt";
58*795d594fSAndroid Build Coastguard Worker constexpr const char* kLlndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/llndk.libraries.{}.txt";
59*795d594fSAndroid Build Coastguard Worker constexpr const char* kLlndkLibrariesNoVndkFile = "/system/etc/llndk.libraries.txt";
60*795d594fSAndroid Build Coastguard Worker constexpr const char* kVndkLibrariesFile = "/apex/com.android.vndk.v{}/etc/vndksp.libraries.{}.txt";
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker // TODO(b/130388701): do we need this?
root_dir()64*795d594fSAndroid Build Coastguard Worker std::string root_dir() {
65*795d594fSAndroid Build Coastguard Worker   static const char* android_root_env = getenv("ANDROID_ROOT");
66*795d594fSAndroid Build Coastguard Worker   return android_root_env != nullptr ? android_root_env : "/system";
67*795d594fSAndroid Build Coastguard Worker }
68*795d594fSAndroid Build Coastguard Worker 
vndk_version_str(bool use_product_vndk)69*795d594fSAndroid Build Coastguard Worker std::string vndk_version_str(bool use_product_vndk) {
70*795d594fSAndroid Build Coastguard Worker   if (use_product_vndk) {
71*795d594fSAndroid Build Coastguard Worker     static std::string product_vndk_version = get_vndk_version(true);
72*795d594fSAndroid Build Coastguard Worker     return product_vndk_version;
73*795d594fSAndroid Build Coastguard Worker   } else {
74*795d594fSAndroid Build Coastguard Worker     static std::string vendor_vndk_version = get_vndk_version(false);
75*795d594fSAndroid Build Coastguard Worker     return vendor_vndk_version;
76*795d594fSAndroid Build Coastguard Worker   }
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker // insert vndk version in every {} placeholder
InsertVndkVersionStr(std::string * file_name,bool use_product_vndk)80*795d594fSAndroid Build Coastguard Worker void InsertVndkVersionStr(std::string* file_name, bool use_product_vndk) {
81*795d594fSAndroid Build Coastguard Worker   CHECK(file_name != nullptr);
82*795d594fSAndroid Build Coastguard Worker   const std::string version = vndk_version_str(use_product_vndk);
83*795d594fSAndroid Build Coastguard Worker   size_t pos = file_name->find("{}");
84*795d594fSAndroid Build Coastguard Worker   while (pos != std::string::npos) {
85*795d594fSAndroid Build Coastguard Worker     file_name->replace(pos, 2, version);
86*795d594fSAndroid Build Coastguard Worker     pos = file_name->find("{}", pos + version.size());
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker }
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker const std::function<Result<bool>(const struct ConfigEntry&)> always_true =
__anon51faff3b0202(const struct ConfigEntry&) 91*795d594fSAndroid Build Coastguard Worker     [](const struct ConfigEntry&) -> Result<bool> { return true; };
92*795d594fSAndroid Build Coastguard Worker 
ReadConfig(const std::string & configFile,const std::function<Result<bool> (const ConfigEntry &)> & filter_fn)93*795d594fSAndroid Build Coastguard Worker Result<std::vector<std::string>> ReadConfig(
94*795d594fSAndroid Build Coastguard Worker     const std::string& configFile,
95*795d594fSAndroid Build Coastguard Worker     const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) {
96*795d594fSAndroid Build Coastguard Worker   std::string file_content;
97*795d594fSAndroid Build Coastguard Worker   if (!base::ReadFileToString(configFile, &file_content)) {
98*795d594fSAndroid Build Coastguard Worker     return ErrnoError() << "Failed to read " << configFile;
99*795d594fSAndroid Build Coastguard Worker   }
100*795d594fSAndroid Build Coastguard Worker   Result<std::vector<std::string>> result = ParseConfig(file_content, filter_fn);
101*795d594fSAndroid Build Coastguard Worker   if (!result.ok()) {
102*795d594fSAndroid Build Coastguard Worker     return Errorf("Cannot parse {}: {}", configFile, result.error().message());
103*795d594fSAndroid Build Coastguard Worker   }
104*795d594fSAndroid Build Coastguard Worker   return result;
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker 
ReadExtensionLibraries(const char * dirname,std::vector<std::string> * sonames)107*795d594fSAndroid Build Coastguard Worker void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) {
108*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname), closedir);
109*795d594fSAndroid Build Coastguard Worker   if (dir != nullptr) {
110*795d594fSAndroid Build Coastguard Worker     // Failing to opening the dir is not an error, which can happen in
111*795d594fSAndroid Build Coastguard Worker     // webview_zygote.
112*795d594fSAndroid Build Coastguard Worker     while (struct dirent* ent = readdir(dir.get())) {
113*795d594fSAndroid Build Coastguard Worker       if (ent->d_type != DT_REG && ent->d_type != DT_LNK) {
114*795d594fSAndroid Build Coastguard Worker         continue;
115*795d594fSAndroid Build Coastguard Worker       }
116*795d594fSAndroid Build Coastguard Worker       const std::string filename(ent->d_name);
117*795d594fSAndroid Build Coastguard Worker       std::string_view fn = filename;
118*795d594fSAndroid Build Coastguard Worker       if (android::base::ConsumePrefix(&fn, kExtendedPublicLibrariesFilePrefix) &&
119*795d594fSAndroid Build Coastguard Worker           android::base::ConsumeSuffix(&fn, kExtendedPublicLibrariesFileSuffix)) {
120*795d594fSAndroid Build Coastguard Worker         const std::string company_name(fn);
121*795d594fSAndroid Build Coastguard Worker         const std::string config_file_path = std::string(dirname) + std::string("/") + filename;
122*795d594fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(
123*795d594fSAndroid Build Coastguard Worker             company_name.empty(),
124*795d594fSAndroid Build Coastguard Worker             "Error extracting company name from public native library list file path \"%s\"",
125*795d594fSAndroid Build Coastguard Worker             config_file_path.c_str());
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker         Result<std::vector<std::string>> ret = ReadConfig(
128*795d594fSAndroid Build Coastguard Worker             config_file_path, [&company_name](const struct ConfigEntry& entry) -> Result<bool> {
129*795d594fSAndroid Build Coastguard Worker               if (entry.soname.starts_with("lib") &&
130*795d594fSAndroid Build Coastguard Worker                   entry.soname.ends_with("." + company_name + ".so")) {
131*795d594fSAndroid Build Coastguard Worker                 return true;
132*795d594fSAndroid Build Coastguard Worker               } else {
133*795d594fSAndroid Build Coastguard Worker                 return Errorf(
134*795d594fSAndroid Build Coastguard Worker                     "Library name \"{}\" does not start with \"lib\" and/or "
135*795d594fSAndroid Build Coastguard Worker                     "does not end with the company name \"{}\".",
136*795d594fSAndroid Build Coastguard Worker                     entry.soname,
137*795d594fSAndroid Build Coastguard Worker                     company_name);
138*795d594fSAndroid Build Coastguard Worker               }
139*795d594fSAndroid Build Coastguard Worker             });
140*795d594fSAndroid Build Coastguard Worker         if (ret.ok()) {
141*795d594fSAndroid Build Coastguard Worker           sonames->insert(sonames->end(), ret->begin(), ret->end());
142*795d594fSAndroid Build Coastguard Worker         } else {
143*795d594fSAndroid Build Coastguard Worker           LOG_ALWAYS_FATAL("Error reading extension library list: %s",
144*795d594fSAndroid Build Coastguard Worker                            ret.error().message().c_str());
145*795d594fSAndroid Build Coastguard Worker         }
146*795d594fSAndroid Build Coastguard Worker       }
147*795d594fSAndroid Build Coastguard Worker     }
148*795d594fSAndroid Build Coastguard Worker   }
149*795d594fSAndroid Build Coastguard Worker }
150*795d594fSAndroid Build Coastguard Worker 
InitDefaultPublicLibraries(bool for_preload)151*795d594fSAndroid Build Coastguard Worker static std::string InitDefaultPublicLibraries(bool for_preload) {
152*795d594fSAndroid Build Coastguard Worker   std::string config_file = root_dir() + kDefaultPublicLibrariesFile;
153*795d594fSAndroid Build Coastguard Worker   Result<std::vector<std::string>> sonames =
154*795d594fSAndroid Build Coastguard Worker       ReadConfig(config_file, [&for_preload](const struct ConfigEntry& entry) -> Result<bool> {
155*795d594fSAndroid Build Coastguard Worker         if (for_preload) {
156*795d594fSAndroid Build Coastguard Worker           return !entry.nopreload;
157*795d594fSAndroid Build Coastguard Worker         } else {
158*795d594fSAndroid Build Coastguard Worker           return true;
159*795d594fSAndroid Build Coastguard Worker         }
160*795d594fSAndroid Build Coastguard Worker       });
161*795d594fSAndroid Build Coastguard Worker   if (!sonames.ok()) {
162*795d594fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
163*795d594fSAndroid Build Coastguard Worker     return "";
164*795d594fSAndroid Build Coastguard Worker   }
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker   // If this is for preloading libs, don't remove the libs from APEXes.
167*795d594fSAndroid Build Coastguard Worker   if (!for_preload) {
168*795d594fSAndroid Build Coastguard Worker     // Remove the public libs provided by apexes because these libs are available
169*795d594fSAndroid Build Coastguard Worker     // from apex namespaces.
170*795d594fSAndroid Build Coastguard Worker     for (const auto& [_, library_list] : apex_public_libraries()) {
171*795d594fSAndroid Build Coastguard Worker       std::vector<std::string> public_libs = base::Split(library_list, ":");
172*795d594fSAndroid Build Coastguard Worker       sonames->erase(std::remove_if(sonames->begin(),
173*795d594fSAndroid Build Coastguard Worker                                     sonames->end(),
174*795d594fSAndroid Build Coastguard Worker                                     [&public_libs](const std::string& v) {
175*795d594fSAndroid Build Coastguard Worker                                       return std::find(public_libs.begin(), public_libs.end(), v) !=
176*795d594fSAndroid Build Coastguard Worker                                              public_libs.end();
177*795d594fSAndroid Build Coastguard Worker                                     }),
178*795d594fSAndroid Build Coastguard Worker                      sonames->end());
179*795d594fSAndroid Build Coastguard Worker     }
180*795d594fSAndroid Build Coastguard Worker   }
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(*sonames, ':');
183*795d594fSAndroid Build Coastguard Worker   ALOGD("InitDefaultPublicLibraries for_preload=%d: %s", for_preload, libs.c_str());
184*795d594fSAndroid Build Coastguard Worker   return libs;
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker 
InitVendorPublicLibraries()187*795d594fSAndroid Build Coastguard Worker static std::string InitVendorPublicLibraries() {
188*795d594fSAndroid Build Coastguard Worker   // This file is optional, quietly ignore if the file does not exist.
189*795d594fSAndroid Build Coastguard Worker   Result<std::vector<std::string>> sonames = ReadConfig(kVendorPublicLibrariesFile, always_true);
190*795d594fSAndroid Build Coastguard Worker   if (!sonames.ok()) {
191*795d594fSAndroid Build Coastguard Worker     ALOGI("InitVendorPublicLibraries skipped: %s", sonames.error().message().c_str());
192*795d594fSAndroid Build Coastguard Worker     return "";
193*795d594fSAndroid Build Coastguard Worker   }
194*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(*sonames, ':');
195*795d594fSAndroid Build Coastguard Worker   ALOGD("InitVendorPublicLibraries: %s", libs.c_str());
196*795d594fSAndroid Build Coastguard Worker   return libs;
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker // If ro.product.vndk.version is defined, /product/etc/public.libraries-<companyname>.txt contains
200*795d594fSAndroid Build Coastguard Worker // the product public libraries that are loaded from the product namespace. Otherwise, the file
201*795d594fSAndroid Build Coastguard Worker // contains the extended public libraries that are loaded from the system namespace.
InitProductPublicLibraries()202*795d594fSAndroid Build Coastguard Worker static std::string InitProductPublicLibraries() {
203*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> sonames;
204*795d594fSAndroid Build Coastguard Worker   if (is_product_treblelized()) {
205*795d594fSAndroid Build Coastguard Worker     ReadExtensionLibraries("/product/etc", &sonames);
206*795d594fSAndroid Build Coastguard Worker   }
207*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(sonames, ':');
208*795d594fSAndroid Build Coastguard Worker   ALOGD("InitProductPublicLibraries: %s", libs.c_str());
209*795d594fSAndroid Build Coastguard Worker   return libs;
210*795d594fSAndroid Build Coastguard Worker }
211*795d594fSAndroid Build Coastguard Worker 
212*795d594fSAndroid Build Coastguard Worker // read /system/etc/public.libraries-<companyname>.txt,
213*795d594fSAndroid Build Coastguard Worker // /system_ext/etc/public.libraries-<companyname>.txt and
214*795d594fSAndroid Build Coastguard Worker // /product/etc/public.libraries-<companyname>.txt which contain partner defined
215*795d594fSAndroid Build Coastguard Worker // system libs that are exposed to apps. The libs in the txt files must be
216*795d594fSAndroid Build Coastguard Worker // named as lib<name>.<companyname>.so.
InitExtendedPublicLibraries()217*795d594fSAndroid Build Coastguard Worker static std::string InitExtendedPublicLibraries() {
218*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> sonames;
219*795d594fSAndroid Build Coastguard Worker   ReadExtensionLibraries("/system/etc", &sonames);
220*795d594fSAndroid Build Coastguard Worker   ReadExtensionLibraries("/system_ext/etc", &sonames);
221*795d594fSAndroid Build Coastguard Worker   if (!is_product_treblelized()) {
222*795d594fSAndroid Build Coastguard Worker     ReadExtensionLibraries("/product/etc", &sonames);
223*795d594fSAndroid Build Coastguard Worker   }
224*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(sonames, ':');
225*795d594fSAndroid Build Coastguard Worker   ALOGD("InitExtendedPublicLibraries: %s", libs.c_str());
226*795d594fSAndroid Build Coastguard Worker   return libs;
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker 
IsVendorVndkEnabled()229*795d594fSAndroid Build Coastguard Worker bool IsVendorVndkEnabled() {
230*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
231*795d594fSAndroid Build Coastguard Worker   return android::base::GetProperty("ro.vndk.version", "") != "";
232*795d594fSAndroid Build Coastguard Worker #else
233*795d594fSAndroid Build Coastguard Worker   return true;
234*795d594fSAndroid Build Coastguard Worker #endif
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker 
IsProductVndkEnabled()237*795d594fSAndroid Build Coastguard Worker bool IsProductVndkEnabled() {
238*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
239*795d594fSAndroid Build Coastguard Worker   return android::base::GetProperty("ro.product.vndk.version", "") != "";
240*795d594fSAndroid Build Coastguard Worker #else
241*795d594fSAndroid Build Coastguard Worker   return true;
242*795d594fSAndroid Build Coastguard Worker #endif
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker 
InitLlndkLibrariesVendor()245*795d594fSAndroid Build Coastguard Worker static std::string InitLlndkLibrariesVendor() {
246*795d594fSAndroid Build Coastguard Worker   std::string config_file;
247*795d594fSAndroid Build Coastguard Worker   if (IsVendorVndkEnabled()) {
248*795d594fSAndroid Build Coastguard Worker     config_file = kLlndkLibrariesFile;
249*795d594fSAndroid Build Coastguard Worker     InsertVndkVersionStr(&config_file, false);
250*795d594fSAndroid Build Coastguard Worker   } else {
251*795d594fSAndroid Build Coastguard Worker     config_file = kLlndkLibrariesNoVndkFile;
252*795d594fSAndroid Build Coastguard Worker   }
253*795d594fSAndroid Build Coastguard Worker   Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
254*795d594fSAndroid Build Coastguard Worker   if (!sonames.ok()) {
255*795d594fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
256*795d594fSAndroid Build Coastguard Worker     return "";
257*795d594fSAndroid Build Coastguard Worker   }
258*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(*sonames, ':');
259*795d594fSAndroid Build Coastguard Worker   ALOGD("InitLlndkLibrariesVendor: %s", libs.c_str());
260*795d594fSAndroid Build Coastguard Worker   return libs;
261*795d594fSAndroid Build Coastguard Worker }
262*795d594fSAndroid Build Coastguard Worker 
InitLlndkLibrariesProduct()263*795d594fSAndroid Build Coastguard Worker static std::string InitLlndkLibrariesProduct() {
264*795d594fSAndroid Build Coastguard Worker   if (!is_product_treblelized()) {
265*795d594fSAndroid Build Coastguard Worker     ALOGD("InitLlndkLibrariesProduct: Product is not treblelized");
266*795d594fSAndroid Build Coastguard Worker     return "";
267*795d594fSAndroid Build Coastguard Worker   }
268*795d594fSAndroid Build Coastguard Worker   std::string config_file;
269*795d594fSAndroid Build Coastguard Worker   if (IsProductVndkEnabled()) {
270*795d594fSAndroid Build Coastguard Worker     config_file = kLlndkLibrariesFile;
271*795d594fSAndroid Build Coastguard Worker     InsertVndkVersionStr(&config_file, true);
272*795d594fSAndroid Build Coastguard Worker   } else {
273*795d594fSAndroid Build Coastguard Worker     config_file = kLlndkLibrariesNoVndkFile;
274*795d594fSAndroid Build Coastguard Worker   }
275*795d594fSAndroid Build Coastguard Worker   Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
276*795d594fSAndroid Build Coastguard Worker   if (!sonames.ok()) {
277*795d594fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
278*795d594fSAndroid Build Coastguard Worker     return "";
279*795d594fSAndroid Build Coastguard Worker   }
280*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(*sonames, ':');
281*795d594fSAndroid Build Coastguard Worker   ALOGD("InitLlndkLibrariesProduct: %s", libs.c_str());
282*795d594fSAndroid Build Coastguard Worker   return libs;
283*795d594fSAndroid Build Coastguard Worker }
284*795d594fSAndroid Build Coastguard Worker 
InitVndkspLibrariesVendor()285*795d594fSAndroid Build Coastguard Worker static std::string InitVndkspLibrariesVendor() {
286*795d594fSAndroid Build Coastguard Worker   if (!IsVendorVndkEnabled()) {
287*795d594fSAndroid Build Coastguard Worker     ALOGD("InitVndkspLibrariesVendor: VNDK is deprecated with vendor");
288*795d594fSAndroid Build Coastguard Worker     return "";
289*795d594fSAndroid Build Coastguard Worker   }
290*795d594fSAndroid Build Coastguard Worker 
291*795d594fSAndroid Build Coastguard Worker   std::string config_file = kVndkLibrariesFile;
292*795d594fSAndroid Build Coastguard Worker   InsertVndkVersionStr(&config_file, false);
293*795d594fSAndroid Build Coastguard Worker   Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
294*795d594fSAndroid Build Coastguard Worker   if (!sonames.ok()) {
295*795d594fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
296*795d594fSAndroid Build Coastguard Worker     return "";
297*795d594fSAndroid Build Coastguard Worker   }
298*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(*sonames, ':');
299*795d594fSAndroid Build Coastguard Worker   ALOGD("InitVndkspLibrariesVendor: %s", libs.c_str());
300*795d594fSAndroid Build Coastguard Worker   return libs;
301*795d594fSAndroid Build Coastguard Worker }
302*795d594fSAndroid Build Coastguard Worker 
InitVndkspLibrariesProduct()303*795d594fSAndroid Build Coastguard Worker static std::string InitVndkspLibrariesProduct() {
304*795d594fSAndroid Build Coastguard Worker   if (!IsProductVndkEnabled()) {
305*795d594fSAndroid Build Coastguard Worker     ALOGD("InitVndkspLibrariesProduct: VNDK is deprecated with product");
306*795d594fSAndroid Build Coastguard Worker     return "";
307*795d594fSAndroid Build Coastguard Worker   }
308*795d594fSAndroid Build Coastguard Worker   std::string config_file = kVndkLibrariesFile;
309*795d594fSAndroid Build Coastguard Worker   InsertVndkVersionStr(&config_file, true);
310*795d594fSAndroid Build Coastguard Worker   Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
311*795d594fSAndroid Build Coastguard Worker   if (!sonames.ok()) {
312*795d594fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
313*795d594fSAndroid Build Coastguard Worker     return "";
314*795d594fSAndroid Build Coastguard Worker   }
315*795d594fSAndroid Build Coastguard Worker   std::string libs = android::base::Join(*sonames, ':');
316*795d594fSAndroid Build Coastguard Worker   ALOGD("InitVndkspLibrariesProduct: %s", libs.c_str());
317*795d594fSAndroid Build Coastguard Worker   return libs;
318*795d594fSAndroid Build Coastguard Worker }
319*795d594fSAndroid Build Coastguard Worker 
InitApexLibraries(const std::string & tag)320*795d594fSAndroid Build Coastguard Worker static std::map<std::string, std::string> InitApexLibraries(const std::string& tag) {
321*795d594fSAndroid Build Coastguard Worker   std::string file_content;
322*795d594fSAndroid Build Coastguard Worker   if (!base::ReadFileToString(kApexLibrariesConfigFile, &file_content)) {
323*795d594fSAndroid Build Coastguard Worker     // config is optional
324*795d594fSAndroid Build Coastguard Worker     ALOGI("InitApexLibraries skipped: %s", strerror(errno));
325*795d594fSAndroid Build Coastguard Worker     return {};
326*795d594fSAndroid Build Coastguard Worker   }
327*795d594fSAndroid Build Coastguard Worker   Result<std::map<std::string, std::string>> config = ParseApexLibrariesConfig(file_content, tag);
328*795d594fSAndroid Build Coastguard Worker   if (!config.ok()) {
329*795d594fSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL("%s: %s", kApexLibrariesConfigFile, config.error().message().c_str());
330*795d594fSAndroid Build Coastguard Worker     return {};
331*795d594fSAndroid Build Coastguard Worker   }
332*795d594fSAndroid Build Coastguard Worker   ALOGD("InitApexLibraries:\n  %s",
333*795d594fSAndroid Build Coastguard Worker         [&config]() {
334*795d594fSAndroid Build Coastguard Worker           std::vector<std::string> lib_list;
335*795d594fSAndroid Build Coastguard Worker           lib_list.reserve(config->size());
336*795d594fSAndroid Build Coastguard Worker           for (std::pair<std::string, std::string> elem : *config) {
337*795d594fSAndroid Build Coastguard Worker             lib_list.emplace_back(elem.first + ": " + elem.second);
338*795d594fSAndroid Build Coastguard Worker           }
339*795d594fSAndroid Build Coastguard Worker           return android::base::Join(lib_list, "\n  ");
340*795d594fSAndroid Build Coastguard Worker         }()
341*795d594fSAndroid Build Coastguard Worker             .c_str());
342*795d594fSAndroid Build Coastguard Worker   return *config;
343*795d594fSAndroid Build Coastguard Worker }
344*795d594fSAndroid Build Coastguard Worker 
345*795d594fSAndroid Build Coastguard Worker struct ApexLibrariesConfigLine {
346*795d594fSAndroid Build Coastguard Worker   std::string tag;
347*795d594fSAndroid Build Coastguard Worker   std::string apex_namespace;
348*795d594fSAndroid Build Coastguard Worker   std::string library_list;
349*795d594fSAndroid Build Coastguard Worker };
350*795d594fSAndroid Build Coastguard Worker 
351*795d594fSAndroid Build Coastguard Worker const std::regex kApexNamespaceRegex("[0-9a-zA-Z_]+");
352*795d594fSAndroid Build Coastguard Worker const std::regex kLibraryListRegex("[0-9a-zA-Z.:@+_-]+");
353*795d594fSAndroid Build Coastguard Worker 
ParseApexLibrariesConfigLine(const std::string & line)354*795d594fSAndroid Build Coastguard Worker Result<ApexLibrariesConfigLine> ParseApexLibrariesConfigLine(const std::string& line) {
355*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> tokens = base::Split(line, " ");
356*795d594fSAndroid Build Coastguard Worker   if (tokens.size() != 3) {
357*795d594fSAndroid Build Coastguard Worker     return Errorf("Malformed line \"{}\"", line);
358*795d594fSAndroid Build Coastguard Worker   }
359*795d594fSAndroid Build Coastguard Worker   if (tokens[0] != "jni" && tokens[0] != "public") {
360*795d594fSAndroid Build Coastguard Worker     return Errorf("Invalid tag \"{}\"", line);
361*795d594fSAndroid Build Coastguard Worker   }
362*795d594fSAndroid Build Coastguard Worker   if (!std::regex_match(tokens[1], kApexNamespaceRegex)) {
363*795d594fSAndroid Build Coastguard Worker     return Errorf("Invalid apex_namespace \"{}\"", line);
364*795d594fSAndroid Build Coastguard Worker   }
365*795d594fSAndroid Build Coastguard Worker   if (!std::regex_match(tokens[2], kLibraryListRegex)) {
366*795d594fSAndroid Build Coastguard Worker     return Errorf("Invalid library_list \"{}\"", line);
367*795d594fSAndroid Build Coastguard Worker   }
368*795d594fSAndroid Build Coastguard Worker   return ApexLibrariesConfigLine{std::move(tokens[0]), std::move(tokens[1]), std::move(tokens[2])};
369*795d594fSAndroid Build Coastguard Worker }
370*795d594fSAndroid Build Coastguard Worker 
371*795d594fSAndroid Build Coastguard Worker }  // namespace
372*795d594fSAndroid Build Coastguard Worker 
preloadable_public_libraries()373*795d594fSAndroid Build Coastguard Worker const std::string& preloadable_public_libraries() {
374*795d594fSAndroid Build Coastguard Worker   static std::string list = InitDefaultPublicLibraries(/*for_preload*/ true);
375*795d594fSAndroid Build Coastguard Worker   return list;
376*795d594fSAndroid Build Coastguard Worker }
377*795d594fSAndroid Build Coastguard Worker 
default_public_libraries()378*795d594fSAndroid Build Coastguard Worker const std::string& default_public_libraries() {
379*795d594fSAndroid Build Coastguard Worker   static std::string list = InitDefaultPublicLibraries(/*for_preload*/ false);
380*795d594fSAndroid Build Coastguard Worker   return list;
381*795d594fSAndroid Build Coastguard Worker }
382*795d594fSAndroid Build Coastguard Worker 
vendor_public_libraries()383*795d594fSAndroid Build Coastguard Worker const std::string& vendor_public_libraries() {
384*795d594fSAndroid Build Coastguard Worker   static std::string list = InitVendorPublicLibraries();
385*795d594fSAndroid Build Coastguard Worker   return list;
386*795d594fSAndroid Build Coastguard Worker }
387*795d594fSAndroid Build Coastguard Worker 
product_public_libraries()388*795d594fSAndroid Build Coastguard Worker const std::string& product_public_libraries() {
389*795d594fSAndroid Build Coastguard Worker   static std::string list = InitProductPublicLibraries();
390*795d594fSAndroid Build Coastguard Worker   return list;
391*795d594fSAndroid Build Coastguard Worker }
392*795d594fSAndroid Build Coastguard Worker 
extended_public_libraries()393*795d594fSAndroid Build Coastguard Worker const std::string& extended_public_libraries() {
394*795d594fSAndroid Build Coastguard Worker   static std::string list = InitExtendedPublicLibraries();
395*795d594fSAndroid Build Coastguard Worker   return list;
396*795d594fSAndroid Build Coastguard Worker }
397*795d594fSAndroid Build Coastguard Worker 
llndk_libraries_product()398*795d594fSAndroid Build Coastguard Worker const std::string& llndk_libraries_product() {
399*795d594fSAndroid Build Coastguard Worker   static std::string list = InitLlndkLibrariesProduct();
400*795d594fSAndroid Build Coastguard Worker   return list;
401*795d594fSAndroid Build Coastguard Worker }
402*795d594fSAndroid Build Coastguard Worker 
llndk_libraries_vendor()403*795d594fSAndroid Build Coastguard Worker const std::string& llndk_libraries_vendor() {
404*795d594fSAndroid Build Coastguard Worker   static std::string list = InitLlndkLibrariesVendor();
405*795d594fSAndroid Build Coastguard Worker   return list;
406*795d594fSAndroid Build Coastguard Worker }
407*795d594fSAndroid Build Coastguard Worker 
vndksp_libraries_product()408*795d594fSAndroid Build Coastguard Worker const std::string& vndksp_libraries_product() {
409*795d594fSAndroid Build Coastguard Worker   static std::string list = InitVndkspLibrariesProduct();
410*795d594fSAndroid Build Coastguard Worker   return list;
411*795d594fSAndroid Build Coastguard Worker }
412*795d594fSAndroid Build Coastguard Worker 
vndksp_libraries_vendor()413*795d594fSAndroid Build Coastguard Worker const std::string& vndksp_libraries_vendor() {
414*795d594fSAndroid Build Coastguard Worker   static std::string list = InitVndkspLibrariesVendor();
415*795d594fSAndroid Build Coastguard Worker   return list;
416*795d594fSAndroid Build Coastguard Worker }
417*795d594fSAndroid Build Coastguard Worker 
apex_jni_libraries(const std::string & apex_ns_name)418*795d594fSAndroid Build Coastguard Worker const std::string& apex_jni_libraries(const std::string& apex_ns_name) {
419*795d594fSAndroid Build Coastguard Worker   static std::map<std::string, std::string> jni_libraries = InitApexLibraries("jni");
420*795d594fSAndroid Build Coastguard Worker   return jni_libraries[apex_ns_name];
421*795d594fSAndroid Build Coastguard Worker }
422*795d594fSAndroid Build Coastguard Worker 
apex_public_libraries()423*795d594fSAndroid Build Coastguard Worker const std::map<std::string, std::string>& apex_public_libraries() {
424*795d594fSAndroid Build Coastguard Worker   static std::map<std::string, std::string> public_libraries = InitApexLibraries("public");
425*795d594fSAndroid Build Coastguard Worker   return public_libraries;
426*795d594fSAndroid Build Coastguard Worker }
427*795d594fSAndroid Build Coastguard Worker 
is_product_treblelized()428*795d594fSAndroid Build Coastguard Worker bool is_product_treblelized() {
429*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
430*795d594fSAndroid Build Coastguard Worker   // Product is treblelized iff the sdk version is newer than U
431*795d594fSAndroid Build Coastguard Worker   // or launching version is R or newer or ro.product.vndk.version is defined
432*795d594fSAndroid Build Coastguard Worker   return android::modules::sdklevel::IsAtLeastV() ||
433*795d594fSAndroid Build Coastguard Worker          android::base::GetIntProperty("ro.product.first_api_level", 0) >= __ANDROID_API_R__ ||
434*795d594fSAndroid Build Coastguard Worker          android::sysprop::VndkProperties::product_vndk_version().has_value();
435*795d594fSAndroid Build Coastguard Worker #else
436*795d594fSAndroid Build Coastguard Worker   return false;
437*795d594fSAndroid Build Coastguard Worker #endif
438*795d594fSAndroid Build Coastguard Worker }
439*795d594fSAndroid Build Coastguard Worker 
get_vndk_version(bool is_product_vndk)440*795d594fSAndroid Build Coastguard Worker std::string get_vndk_version(bool is_product_vndk) {
441*795d594fSAndroid Build Coastguard Worker #if defined(ART_TARGET_ANDROID)
442*795d594fSAndroid Build Coastguard Worker   if (is_product_vndk) {
443*795d594fSAndroid Build Coastguard Worker     return android::sysprop::VndkProperties::product_vndk_version().value_or("");
444*795d594fSAndroid Build Coastguard Worker   }
445*795d594fSAndroid Build Coastguard Worker   return android::sysprop::VndkProperties::vendor_vndk_version().value_or("");
446*795d594fSAndroid Build Coastguard Worker #else
447*795d594fSAndroid Build Coastguard Worker   if (is_product_vndk) {
448*795d594fSAndroid Build Coastguard Worker     return android::base::GetProperty("ro.product.vndk.version", "");
449*795d594fSAndroid Build Coastguard Worker   }
450*795d594fSAndroid Build Coastguard Worker   return android::base::GetProperty("ro.vndk.version", "");
451*795d594fSAndroid Build Coastguard Worker #endif
452*795d594fSAndroid Build Coastguard Worker }
453*795d594fSAndroid Build Coastguard Worker 
454*795d594fSAndroid Build Coastguard Worker namespace internal {
455*795d594fSAndroid Build Coastguard Worker // Exported for testing
ParseConfig(const std::string & file_content,const std::function<Result<bool> (const ConfigEntry &)> & filter_fn)456*795d594fSAndroid Build Coastguard Worker Result<std::vector<std::string>> ParseConfig(
457*795d594fSAndroid Build Coastguard Worker     const std::string& file_content,
458*795d594fSAndroid Build Coastguard Worker     const std::function<Result<bool>(const ConfigEntry& /* entry */)>& filter_fn) {
459*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> lines = base::Split(file_content, "\n");
460*795d594fSAndroid Build Coastguard Worker 
461*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> sonames;
462*795d594fSAndroid Build Coastguard Worker   for (std::string& line : lines) {
463*795d594fSAndroid Build Coastguard Worker     std::string trimmed_line = base::Trim(line);
464*795d594fSAndroid Build Coastguard Worker     if (trimmed_line[0] == '#' || trimmed_line.empty()) {
465*795d594fSAndroid Build Coastguard Worker       continue;
466*795d594fSAndroid Build Coastguard Worker     }
467*795d594fSAndroid Build Coastguard Worker 
468*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> tokens = android::base::Split(trimmed_line, " ");
469*795d594fSAndroid Build Coastguard Worker     if (tokens.size() < 1 || tokens.size() > 3) {
470*795d594fSAndroid Build Coastguard Worker       return Errorf("Malformed line \"{}\"", line);
471*795d594fSAndroid Build Coastguard Worker     }
472*795d594fSAndroid Build Coastguard Worker     struct ConfigEntry entry = {.soname = "", .nopreload = false, .bitness = ALL};
473*795d594fSAndroid Build Coastguard Worker     size_t i = tokens.size();
474*795d594fSAndroid Build Coastguard Worker     while (i-- > 0) {
475*795d594fSAndroid Build Coastguard Worker       if (tokens[i] == "nopreload") {
476*795d594fSAndroid Build Coastguard Worker         entry.nopreload = true;
477*795d594fSAndroid Build Coastguard Worker       } else if (tokens[i] == "32" || tokens[i] == "64") {
478*795d594fSAndroid Build Coastguard Worker         if (entry.bitness != ALL) {
479*795d594fSAndroid Build Coastguard Worker           return Errorf("Malformed line \"{}\": bitness can be specified only once", line);
480*795d594fSAndroid Build Coastguard Worker         }
481*795d594fSAndroid Build Coastguard Worker         entry.bitness = tokens[i] == "32" ? ONLY_32 : ONLY_64;
482*795d594fSAndroid Build Coastguard Worker       } else {
483*795d594fSAndroid Build Coastguard Worker         if (i != 0) {
484*795d594fSAndroid Build Coastguard Worker           return Errorf("Malformed line \"{}\"", line);
485*795d594fSAndroid Build Coastguard Worker         }
486*795d594fSAndroid Build Coastguard Worker         entry.soname = tokens[i];
487*795d594fSAndroid Build Coastguard Worker       }
488*795d594fSAndroid Build Coastguard Worker     }
489*795d594fSAndroid Build Coastguard Worker 
490*795d594fSAndroid Build Coastguard Worker     // skip 32-bit lib on 64-bit process and vice versa
491*795d594fSAndroid Build Coastguard Worker #if defined(__LP64__)
492*795d594fSAndroid Build Coastguard Worker     if (entry.bitness == ONLY_32) continue;
493*795d594fSAndroid Build Coastguard Worker #else
494*795d594fSAndroid Build Coastguard Worker     if (entry.bitness == ONLY_64) continue;
495*795d594fSAndroid Build Coastguard Worker #endif
496*795d594fSAndroid Build Coastguard Worker 
497*795d594fSAndroid Build Coastguard Worker     // TODO(b/206676167): Remove this check when renderscript is officially removed.
498*795d594fSAndroid Build Coastguard Worker #if defined(__riscv)
499*795d594fSAndroid Build Coastguard Worker     // skip renderscript lib on riscv target
500*795d594fSAndroid Build Coastguard Worker     if (entry.soname == "libRS.so") continue;
501*795d594fSAndroid Build Coastguard Worker #endif
502*795d594fSAndroid Build Coastguard Worker 
503*795d594fSAndroid Build Coastguard Worker     Result<bool> ret = filter_fn(entry);
504*795d594fSAndroid Build Coastguard Worker     if (!ret.ok()) {
505*795d594fSAndroid Build Coastguard Worker       return ret.error();
506*795d594fSAndroid Build Coastguard Worker     }
507*795d594fSAndroid Build Coastguard Worker     if (*ret) {
508*795d594fSAndroid Build Coastguard Worker       // filter_fn has returned true.
509*795d594fSAndroid Build Coastguard Worker       sonames.push_back(entry.soname);
510*795d594fSAndroid Build Coastguard Worker     }
511*795d594fSAndroid Build Coastguard Worker   }
512*795d594fSAndroid Build Coastguard Worker   return sonames;
513*795d594fSAndroid Build Coastguard Worker }
514*795d594fSAndroid Build Coastguard Worker 
515*795d594fSAndroid Build Coastguard Worker // Parses apex.libraries.config.txt file generated by linkerconfig which looks like
516*795d594fSAndroid Build Coastguard Worker //   system/linkerconfig/testdata/golden_output/stages/apex.libraries.config.txt
517*795d594fSAndroid Build Coastguard Worker // and returns mapping of <apex namespace> to <library list> which matches <tag>.
518*795d594fSAndroid Build Coastguard Worker //
519*795d594fSAndroid Build Coastguard Worker // The file is line-based and each line consists of "<tag> <apex namespace> <library list>".
520*795d594fSAndroid Build Coastguard Worker //
521*795d594fSAndroid Build Coastguard Worker // <tag> explains what <library list> is. (e.g "jni", "public")
522*795d594fSAndroid Build Coastguard Worker // <library list> is colon-separated list of library names. (e.g "libfoo.so:libbar.so")
523*795d594fSAndroid Build Coastguard Worker //
524*795d594fSAndroid Build Coastguard Worker // If <tag> is "jni", <library list> is the list of JNI libraries exposed by <apex namespace>.
525*795d594fSAndroid Build Coastguard Worker // If <tag> is "public", <library list> is the list of public libraries exposed by <apex namespace>.
526*795d594fSAndroid Build Coastguard Worker // Public libraries are the libs listed in /system/etc/public.libraries.txt.
ParseApexLibrariesConfig(const std::string & file_content,const std::string & tag)527*795d594fSAndroid Build Coastguard Worker Result<std::map<std::string, std::string>> ParseApexLibrariesConfig(const std::string& file_content, const std::string& tag) {
528*795d594fSAndroid Build Coastguard Worker   std::map<std::string, std::string> entries;
529*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> lines = base::Split(file_content, "\n");
530*795d594fSAndroid Build Coastguard Worker   for (std::string& line : lines) {
531*795d594fSAndroid Build Coastguard Worker     std::string trimmed_line = base::Trim(line);
532*795d594fSAndroid Build Coastguard Worker     if (trimmed_line[0] == '#' || trimmed_line.empty()) {
533*795d594fSAndroid Build Coastguard Worker       continue;
534*795d594fSAndroid Build Coastguard Worker     }
535*795d594fSAndroid Build Coastguard Worker     Result<ApexLibrariesConfigLine> config_line = ParseApexLibrariesConfigLine(trimmed_line);
536*795d594fSAndroid Build Coastguard Worker     if (!config_line.ok()) {
537*795d594fSAndroid Build Coastguard Worker       return config_line.error();
538*795d594fSAndroid Build Coastguard Worker     }
539*795d594fSAndroid Build Coastguard Worker     if (config_line->tag != tag) {
540*795d594fSAndroid Build Coastguard Worker       continue;
541*795d594fSAndroid Build Coastguard Worker     }
542*795d594fSAndroid Build Coastguard Worker     entries[config_line->apex_namespace] = config_line->library_list;
543*795d594fSAndroid Build Coastguard Worker   }
544*795d594fSAndroid Build Coastguard Worker   return entries;
545*795d594fSAndroid Build Coastguard Worker }
546*795d594fSAndroid Build Coastguard Worker 
547*795d594fSAndroid Build Coastguard Worker }  // namespace internal
548*795d594fSAndroid Build Coastguard Worker 
549*795d594fSAndroid Build Coastguard Worker }  // namespace android::nativeloader
550