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