1*e5eeaa8eSAndroid Build Coastguard Worker /*
2*e5eeaa8eSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*e5eeaa8eSAndroid Build Coastguard Worker *
4*e5eeaa8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e5eeaa8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e5eeaa8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e5eeaa8eSAndroid Build Coastguard Worker *
8*e5eeaa8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e5eeaa8eSAndroid Build Coastguard Worker *
10*e5eeaa8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e5eeaa8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e5eeaa8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e5eeaa8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e5eeaa8eSAndroid Build Coastguard Worker * limitations under the License.
15*e5eeaa8eSAndroid Build Coastguard Worker */
16*e5eeaa8eSAndroid Build Coastguard Worker
17*e5eeaa8eSAndroid Build Coastguard Worker #include <climits>
18*e5eeaa8eSAndroid Build Coastguard Worker #include <cstdlib>
19*e5eeaa8eSAndroid Build Coastguard Worker #include <cstring>
20*e5eeaa8eSAndroid Build Coastguard Worker #include <fstream>
21*e5eeaa8eSAndroid Build Coastguard Worker #include <iostream>
22*e5eeaa8eSAndroid Build Coastguard Worker #include <string>
23*e5eeaa8eSAndroid Build Coastguard Worker
24*e5eeaa8eSAndroid Build Coastguard Worker #include <errno.h>
25*e5eeaa8eSAndroid Build Coastguard Worker #include <fcntl.h>
26*e5eeaa8eSAndroid Build Coastguard Worker #include <getopt.h>
27*e5eeaa8eSAndroid Build Coastguard Worker #include <sys/stat.h>
28*e5eeaa8eSAndroid Build Coastguard Worker #include <sys/types.h>
29*e5eeaa8eSAndroid Build Coastguard Worker
30*e5eeaa8eSAndroid Build Coastguard Worker #include <android-base/result.h>
31*e5eeaa8eSAndroid Build Coastguard Worker #include <android-base/strings.h>
32*e5eeaa8eSAndroid Build Coastguard Worker
33*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/apex.h"
34*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/apexconfig.h"
35*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/baseconfig.h"
36*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/configparser.h"
37*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/context.h"
38*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/environment.h"
39*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/legacy.h"
40*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/log.h"
41*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/namespacebuilder.h"
42*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/recovery.h"
43*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/variableloader.h"
44*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/variables.h"
45*e5eeaa8eSAndroid Build Coastguard Worker
46*e5eeaa8eSAndroid Build Coastguard Worker using android::base::ErrnoError;
47*e5eeaa8eSAndroid Build Coastguard Worker using android::base::Error;
48*e5eeaa8eSAndroid Build Coastguard Worker using android::base::Join;
49*e5eeaa8eSAndroid Build Coastguard Worker using android::base::Result;
50*e5eeaa8eSAndroid Build Coastguard Worker using android::linkerconfig::contents::Context;
51*e5eeaa8eSAndroid Build Coastguard Worker using android::linkerconfig::modules::ApexInfo;
52*e5eeaa8eSAndroid Build Coastguard Worker using android::linkerconfig::modules::Configuration;
53*e5eeaa8eSAndroid Build Coastguard Worker
54*e5eeaa8eSAndroid Build Coastguard Worker namespace {
55*e5eeaa8eSAndroid Build Coastguard Worker const static struct option program_options[] = {
56*e5eeaa8eSAndroid Build Coastguard Worker {"apex", required_argument, 0, 'a'},
57*e5eeaa8eSAndroid Build Coastguard Worker {"target", required_argument, 0, 't'},
58*e5eeaa8eSAndroid Build Coastguard Worker {"strict", no_argument, 0, 's'},
59*e5eeaa8eSAndroid Build Coastguard Worker #ifndef __ANDROID__
60*e5eeaa8eSAndroid Build Coastguard Worker {"root", required_argument, 0, 'r'},
61*e5eeaa8eSAndroid Build Coastguard Worker {"vndk", required_argument, 0, 'v'},
62*e5eeaa8eSAndroid Build Coastguard Worker {"product_vndk", required_argument, 0, 'p'},
63*e5eeaa8eSAndroid Build Coastguard Worker {"deprecate_vndk", no_argument, 0, 'd'},
64*e5eeaa8eSAndroid Build Coastguard Worker {"recovery", no_argument, 0, 'y'},
65*e5eeaa8eSAndroid Build Coastguard Worker {"treblelize", no_argument, 0, 'z'},
66*e5eeaa8eSAndroid Build Coastguard Worker #endif
67*e5eeaa8eSAndroid Build Coastguard Worker {"help", no_argument, 0, 'h'},
68*e5eeaa8eSAndroid Build Coastguard Worker {0, 0, 0, 0}};
69*e5eeaa8eSAndroid Build Coastguard Worker
70*e5eeaa8eSAndroid Build Coastguard Worker struct ProgramArgs {
71*e5eeaa8eSAndroid Build Coastguard Worker std::string target_apex;
72*e5eeaa8eSAndroid Build Coastguard Worker std::string target_directory;
73*e5eeaa8eSAndroid Build Coastguard Worker bool strict;
74*e5eeaa8eSAndroid Build Coastguard Worker std::string root;
75*e5eeaa8eSAndroid Build Coastguard Worker std::string vndk_version;
76*e5eeaa8eSAndroid Build Coastguard Worker std::string product_vndk_version;
77*e5eeaa8eSAndroid Build Coastguard Worker bool is_recovery;
78*e5eeaa8eSAndroid Build Coastguard Worker bool deprecate_vndk;
79*e5eeaa8eSAndroid Build Coastguard Worker bool is_treblelized;
80*e5eeaa8eSAndroid Build Coastguard Worker };
81*e5eeaa8eSAndroid Build Coastguard Worker
PrintUsage(int status=EXIT_SUCCESS)82*e5eeaa8eSAndroid Build Coastguard Worker [[noreturn]] void PrintUsage(int status = EXIT_SUCCESS) {
83*e5eeaa8eSAndroid Build Coastguard Worker std::cerr << "Usage : linkerconfig [--target <target_directory>]"
84*e5eeaa8eSAndroid Build Coastguard Worker " [--strict]"
85*e5eeaa8eSAndroid Build Coastguard Worker " --apex <name>"
86*e5eeaa8eSAndroid Build Coastguard Worker #ifndef __ANDROID__
87*e5eeaa8eSAndroid Build Coastguard Worker " --root <root dir>"
88*e5eeaa8eSAndroid Build Coastguard Worker " --vndk <vndk version>"
89*e5eeaa8eSAndroid Build Coastguard Worker " --product_vndk <product vndk version>"
90*e5eeaa8eSAndroid Build Coastguard Worker " --recovery"
91*e5eeaa8eSAndroid Build Coastguard Worker " --treblelize"
92*e5eeaa8eSAndroid Build Coastguard Worker #endif
93*e5eeaa8eSAndroid Build Coastguard Worker " [--help]"
94*e5eeaa8eSAndroid Build Coastguard Worker << std::endl;
95*e5eeaa8eSAndroid Build Coastguard Worker exit(status);
96*e5eeaa8eSAndroid Build Coastguard Worker }
97*e5eeaa8eSAndroid Build Coastguard Worker
RealPath(std::string_view path)98*e5eeaa8eSAndroid Build Coastguard Worker std::string RealPath(std::string_view path) {
99*e5eeaa8eSAndroid Build Coastguard Worker char resolved_path[PATH_MAX];
100*e5eeaa8eSAndroid Build Coastguard Worker if (realpath(path.data(), resolved_path) != nullptr) {
101*e5eeaa8eSAndroid Build Coastguard Worker return resolved_path;
102*e5eeaa8eSAndroid Build Coastguard Worker }
103*e5eeaa8eSAndroid Build Coastguard Worker PrintUsage(-1);
104*e5eeaa8eSAndroid Build Coastguard Worker }
105*e5eeaa8eSAndroid Build Coastguard Worker
ParseArgs(int argc,char * argv[],ProgramArgs * args)106*e5eeaa8eSAndroid Build Coastguard Worker bool ParseArgs(int argc, char* argv[], ProgramArgs* args) {
107*e5eeaa8eSAndroid Build Coastguard Worker int parse_result;
108*e5eeaa8eSAndroid Build Coastguard Worker while ((parse_result = getopt_long(
109*e5eeaa8eSAndroid Build Coastguard Worker argc, argv, "a:t:sr:v:ep:hzyl", program_options, NULL)) != -1) {
110*e5eeaa8eSAndroid Build Coastguard Worker switch (parse_result) {
111*e5eeaa8eSAndroid Build Coastguard Worker case 'a':
112*e5eeaa8eSAndroid Build Coastguard Worker args->target_apex = optarg;
113*e5eeaa8eSAndroid Build Coastguard Worker break;
114*e5eeaa8eSAndroid Build Coastguard Worker case 't':
115*e5eeaa8eSAndroid Build Coastguard Worker args->target_directory = optarg;
116*e5eeaa8eSAndroid Build Coastguard Worker break;
117*e5eeaa8eSAndroid Build Coastguard Worker case 's':
118*e5eeaa8eSAndroid Build Coastguard Worker args->strict = true;
119*e5eeaa8eSAndroid Build Coastguard Worker break;
120*e5eeaa8eSAndroid Build Coastguard Worker case 'r':
121*e5eeaa8eSAndroid Build Coastguard Worker args->root = RealPath(optarg);
122*e5eeaa8eSAndroid Build Coastguard Worker break;
123*e5eeaa8eSAndroid Build Coastguard Worker case 'v':
124*e5eeaa8eSAndroid Build Coastguard Worker args->vndk_version = optarg;
125*e5eeaa8eSAndroid Build Coastguard Worker break;
126*e5eeaa8eSAndroid Build Coastguard Worker case 'p':
127*e5eeaa8eSAndroid Build Coastguard Worker args->product_vndk_version = optarg;
128*e5eeaa8eSAndroid Build Coastguard Worker break;
129*e5eeaa8eSAndroid Build Coastguard Worker case 'z':
130*e5eeaa8eSAndroid Build Coastguard Worker args->is_treblelized = true;
131*e5eeaa8eSAndroid Build Coastguard Worker break;
132*e5eeaa8eSAndroid Build Coastguard Worker case 'y':
133*e5eeaa8eSAndroid Build Coastguard Worker args->is_recovery = true;
134*e5eeaa8eSAndroid Build Coastguard Worker break;
135*e5eeaa8eSAndroid Build Coastguard Worker case 'h':
136*e5eeaa8eSAndroid Build Coastguard Worker PrintUsage();
137*e5eeaa8eSAndroid Build Coastguard Worker default:
138*e5eeaa8eSAndroid Build Coastguard Worker return false;
139*e5eeaa8eSAndroid Build Coastguard Worker }
140*e5eeaa8eSAndroid Build Coastguard Worker }
141*e5eeaa8eSAndroid Build Coastguard Worker
142*e5eeaa8eSAndroid Build Coastguard Worker if (optind < argc) {
143*e5eeaa8eSAndroid Build Coastguard Worker return false;
144*e5eeaa8eSAndroid Build Coastguard Worker }
145*e5eeaa8eSAndroid Build Coastguard Worker
146*e5eeaa8eSAndroid Build Coastguard Worker return true;
147*e5eeaa8eSAndroid Build Coastguard Worker }
148*e5eeaa8eSAndroid Build Coastguard Worker
LoadVariables(const ProgramArgs & args)149*e5eeaa8eSAndroid Build Coastguard Worker void LoadVariables(const ProgramArgs& args) {
150*e5eeaa8eSAndroid Build Coastguard Worker #ifndef __ANDROID__
151*e5eeaa8eSAndroid Build Coastguard Worker if (!args.is_recovery && args.root == "") {
152*e5eeaa8eSAndroid Build Coastguard Worker PrintUsage();
153*e5eeaa8eSAndroid Build Coastguard Worker }
154*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::Variables::AddValue("ro.vndk.version",
155*e5eeaa8eSAndroid Build Coastguard Worker args.vndk_version);
156*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::Variables::AddValue(
157*e5eeaa8eSAndroid Build Coastguard Worker "ro.product.vndk.version", args.product_vndk_version);
158*e5eeaa8eSAndroid Build Coastguard Worker
159*e5eeaa8eSAndroid Build Coastguard Worker if (args.is_treblelized) {
160*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::Variables::AddValue("ro.treble.enabled",
161*e5eeaa8eSAndroid Build Coastguard Worker "true");
162*e5eeaa8eSAndroid Build Coastguard Worker }
163*e5eeaa8eSAndroid Build Coastguard Worker #endif
164*e5eeaa8eSAndroid Build Coastguard Worker if (!args.is_recovery) {
165*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::generator::LoadVariables(args.root);
166*e5eeaa8eSAndroid Build Coastguard Worker }
167*e5eeaa8eSAndroid Build Coastguard Worker }
168*e5eeaa8eSAndroid Build Coastguard Worker
WriteConfigurationToFile(Configuration & conf,std::string file_path)169*e5eeaa8eSAndroid Build Coastguard Worker Result<void> WriteConfigurationToFile(Configuration& conf,
170*e5eeaa8eSAndroid Build Coastguard Worker std::string file_path) {
171*e5eeaa8eSAndroid Build Coastguard Worker std::ostream* out = &std::cout;
172*e5eeaa8eSAndroid Build Coastguard Worker std::ofstream file_out;
173*e5eeaa8eSAndroid Build Coastguard Worker
174*e5eeaa8eSAndroid Build Coastguard Worker if (file_path != "") {
175*e5eeaa8eSAndroid Build Coastguard Worker file_out.open(file_path);
176*e5eeaa8eSAndroid Build Coastguard Worker if (file_out.fail()) {
177*e5eeaa8eSAndroid Build Coastguard Worker return ErrnoError() << "Failed to open file " << file_path;
178*e5eeaa8eSAndroid Build Coastguard Worker }
179*e5eeaa8eSAndroid Build Coastguard Worker out = &file_out;
180*e5eeaa8eSAndroid Build Coastguard Worker }
181*e5eeaa8eSAndroid Build Coastguard Worker
182*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::ConfigWriter config_writer;
183*e5eeaa8eSAndroid Build Coastguard Worker
184*e5eeaa8eSAndroid Build Coastguard Worker conf.WriteConfig(config_writer);
185*e5eeaa8eSAndroid Build Coastguard Worker *out << config_writer.ToString();
186*e5eeaa8eSAndroid Build Coastguard Worker if (!out->good()) {
187*e5eeaa8eSAndroid Build Coastguard Worker return ErrnoError() << "Failed to write content to " << file_path;
188*e5eeaa8eSAndroid Build Coastguard Worker }
189*e5eeaa8eSAndroid Build Coastguard Worker
190*e5eeaa8eSAndroid Build Coastguard Worker return {};
191*e5eeaa8eSAndroid Build Coastguard Worker }
192*e5eeaa8eSAndroid Build Coastguard Worker
UpdatePermission(const std::string & file_path)193*e5eeaa8eSAndroid Build Coastguard Worker Result<void> UpdatePermission([[maybe_unused]] const std::string& file_path) {
194*e5eeaa8eSAndroid Build Coastguard Worker #ifdef __ANDROID__
195*e5eeaa8eSAndroid Build Coastguard Worker if (fchmodat(AT_FDCWD,
196*e5eeaa8eSAndroid Build Coastguard Worker file_path.c_str(),
197*e5eeaa8eSAndroid Build Coastguard Worker S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
198*e5eeaa8eSAndroid Build Coastguard Worker AT_SYMLINK_NOFOLLOW) < 0) {
199*e5eeaa8eSAndroid Build Coastguard Worker return ErrnoError() << "Failed to update permission of " << file_path;
200*e5eeaa8eSAndroid Build Coastguard Worker }
201*e5eeaa8eSAndroid Build Coastguard Worker #endif
202*e5eeaa8eSAndroid Build Coastguard Worker
203*e5eeaa8eSAndroid Build Coastguard Worker return {};
204*e5eeaa8eSAndroid Build Coastguard Worker }
205*e5eeaa8eSAndroid Build Coastguard Worker
GetContext(const ProgramArgs & args)206*e5eeaa8eSAndroid Build Coastguard Worker Context GetContext(const ProgramArgs& args) {
207*e5eeaa8eSAndroid Build Coastguard Worker Context ctx;
208*e5eeaa8eSAndroid Build Coastguard Worker if (args.strict) {
209*e5eeaa8eSAndroid Build Coastguard Worker ctx.SetStrictMode(true);
210*e5eeaa8eSAndroid Build Coastguard Worker }
211*e5eeaa8eSAndroid Build Coastguard Worker if (!args.target_apex.empty()) {
212*e5eeaa8eSAndroid Build Coastguard Worker ctx.SetTargetApex(args.target_apex);
213*e5eeaa8eSAndroid Build Coastguard Worker }
214*e5eeaa8eSAndroid Build Coastguard Worker if (!args.is_recovery) {
215*e5eeaa8eSAndroid Build Coastguard Worker auto apex_list = android::linkerconfig::modules::ScanActiveApexes(args.root);
216*e5eeaa8eSAndroid Build Coastguard Worker if (apex_list.ok()) {
217*e5eeaa8eSAndroid Build Coastguard Worker std::vector<ApexInfo> apex_modules;
218*e5eeaa8eSAndroid Build Coastguard Worker for (auto const& apex_item : *apex_list) {
219*e5eeaa8eSAndroid Build Coastguard Worker auto apex_info = apex_item.second;
220*e5eeaa8eSAndroid Build Coastguard Worker if (apex_info.has_bin || apex_info.has_lib) {
221*e5eeaa8eSAndroid Build Coastguard Worker apex_modules.push_back(std::move(apex_info));
222*e5eeaa8eSAndroid Build Coastguard Worker }
223*e5eeaa8eSAndroid Build Coastguard Worker }
224*e5eeaa8eSAndroid Build Coastguard Worker ctx.SetApexModules(std::move(apex_modules));
225*e5eeaa8eSAndroid Build Coastguard Worker } else {
226*e5eeaa8eSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to scan APEX modules : " << apex_list.error();
227*e5eeaa8eSAndroid Build Coastguard Worker }
228*e5eeaa8eSAndroid Build Coastguard Worker }
229*e5eeaa8eSAndroid Build Coastguard Worker
230*e5eeaa8eSAndroid Build Coastguard Worker std::string system_config_path = args.root + "/system/etc/linker.config.pb";
231*e5eeaa8eSAndroid Build Coastguard Worker if (access(system_config_path.c_str(), F_OK) == 0) {
232*e5eeaa8eSAndroid Build Coastguard Worker auto system_config =
233*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::ParseLinkerConfig(system_config_path);
234*e5eeaa8eSAndroid Build Coastguard Worker if (system_config.ok()) {
235*e5eeaa8eSAndroid Build Coastguard Worker ctx.SetSystemConfig(*system_config);
236*e5eeaa8eSAndroid Build Coastguard Worker } else {
237*e5eeaa8eSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to read system config : " << system_config.error();
238*e5eeaa8eSAndroid Build Coastguard Worker }
239*e5eeaa8eSAndroid Build Coastguard Worker }
240*e5eeaa8eSAndroid Build Coastguard Worker
241*e5eeaa8eSAndroid Build Coastguard Worker std::string system_ext_config_path =
242*e5eeaa8eSAndroid Build Coastguard Worker args.root + "/system_ext/etc/linker.config.pb";
243*e5eeaa8eSAndroid Build Coastguard Worker if (access(system_ext_config_path.c_str(), F_OK) == 0) {
244*e5eeaa8eSAndroid Build Coastguard Worker auto system_ext_config = android::linkerconfig::modules::ParseLinkerConfig(
245*e5eeaa8eSAndroid Build Coastguard Worker system_ext_config_path);
246*e5eeaa8eSAndroid Build Coastguard Worker if (system_ext_config.ok()) {
247*e5eeaa8eSAndroid Build Coastguard Worker ctx.SetSystemConfig(*system_ext_config);
248*e5eeaa8eSAndroid Build Coastguard Worker } else {
249*e5eeaa8eSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to read system_ext config : "
250*e5eeaa8eSAndroid Build Coastguard Worker << system_ext_config.error();
251*e5eeaa8eSAndroid Build Coastguard Worker }
252*e5eeaa8eSAndroid Build Coastguard Worker }
253*e5eeaa8eSAndroid Build Coastguard Worker
254*e5eeaa8eSAndroid Build Coastguard Worker std::string vendor_config_path = args.root + "/vendor/etc/linker.config.pb";
255*e5eeaa8eSAndroid Build Coastguard Worker if (access(vendor_config_path.c_str(), F_OK) == 0) {
256*e5eeaa8eSAndroid Build Coastguard Worker auto vendor_config =
257*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::ParseLinkerConfig(vendor_config_path);
258*e5eeaa8eSAndroid Build Coastguard Worker if (vendor_config.ok()) {
259*e5eeaa8eSAndroid Build Coastguard Worker ctx.SetVendorConfig(*vendor_config);
260*e5eeaa8eSAndroid Build Coastguard Worker } else {
261*e5eeaa8eSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to read vendor config : " << vendor_config.error();
262*e5eeaa8eSAndroid Build Coastguard Worker }
263*e5eeaa8eSAndroid Build Coastguard Worker }
264*e5eeaa8eSAndroid Build Coastguard Worker
265*e5eeaa8eSAndroid Build Coastguard Worker std::string product_config_path = args.root + "/product/etc/linker.config.pb";
266*e5eeaa8eSAndroid Build Coastguard Worker if (access(product_config_path.c_str(), F_OK) == 0) {
267*e5eeaa8eSAndroid Build Coastguard Worker auto product_config =
268*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::ParseLinkerConfig(product_config_path);
269*e5eeaa8eSAndroid Build Coastguard Worker if (product_config.ok()) {
270*e5eeaa8eSAndroid Build Coastguard Worker ctx.SetProductConfig(*product_config);
271*e5eeaa8eSAndroid Build Coastguard Worker } else {
272*e5eeaa8eSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to read product config : " << product_config.error();
273*e5eeaa8eSAndroid Build Coastguard Worker }
274*e5eeaa8eSAndroid Build Coastguard Worker }
275*e5eeaa8eSAndroid Build Coastguard Worker return ctx;
276*e5eeaa8eSAndroid Build Coastguard Worker }
277*e5eeaa8eSAndroid Build Coastguard Worker
GetConfiguration(Context & ctx)278*e5eeaa8eSAndroid Build Coastguard Worker Configuration GetConfiguration(Context& ctx) {
279*e5eeaa8eSAndroid Build Coastguard Worker if (android::linkerconfig::modules::IsRecoveryMode()) {
280*e5eeaa8eSAndroid Build Coastguard Worker return android::linkerconfig::contents::CreateRecoveryConfiguration(ctx);
281*e5eeaa8eSAndroid Build Coastguard Worker }
282*e5eeaa8eSAndroid Build Coastguard Worker
283*e5eeaa8eSAndroid Build Coastguard Worker if (!android::linkerconfig::modules::IsTreblelizedDevice()) {
284*e5eeaa8eSAndroid Build Coastguard Worker return android::linkerconfig::contents::CreateLegacyConfiguration(ctx);
285*e5eeaa8eSAndroid Build Coastguard Worker }
286*e5eeaa8eSAndroid Build Coastguard Worker
287*e5eeaa8eSAndroid Build Coastguard Worker // Use base configuration in default
288*e5eeaa8eSAndroid Build Coastguard Worker return android::linkerconfig::contents::CreateBaseConfiguration(ctx);
289*e5eeaa8eSAndroid Build Coastguard Worker }
290*e5eeaa8eSAndroid Build Coastguard Worker
GenerateConfiguration(Configuration config,const std::string & dir_path,bool update_permission)291*e5eeaa8eSAndroid Build Coastguard Worker Result<void> GenerateConfiguration(Configuration config,
292*e5eeaa8eSAndroid Build Coastguard Worker const std::string& dir_path,
293*e5eeaa8eSAndroid Build Coastguard Worker bool update_permission) {
294*e5eeaa8eSAndroid Build Coastguard Worker std::string file_path = "";
295*e5eeaa8eSAndroid Build Coastguard Worker if (dir_path != "") {
296*e5eeaa8eSAndroid Build Coastguard Worker file_path = dir_path + "/ld.config.txt";
297*e5eeaa8eSAndroid Build Coastguard Worker }
298*e5eeaa8eSAndroid Build Coastguard Worker
299*e5eeaa8eSAndroid Build Coastguard Worker auto write_config = WriteConfigurationToFile(config, file_path);
300*e5eeaa8eSAndroid Build Coastguard Worker if (!write_config.ok()) {
301*e5eeaa8eSAndroid Build Coastguard Worker return write_config;
302*e5eeaa8eSAndroid Build Coastguard Worker } else if (update_permission && file_path != "") {
303*e5eeaa8eSAndroid Build Coastguard Worker return UpdatePermission(file_path);
304*e5eeaa8eSAndroid Build Coastguard Worker }
305*e5eeaa8eSAndroid Build Coastguard Worker
306*e5eeaa8eSAndroid Build Coastguard Worker return {};
307*e5eeaa8eSAndroid Build Coastguard Worker }
308*e5eeaa8eSAndroid Build Coastguard Worker
GenerateBaseLinkerConfiguration(Context & ctx,const std::string & dir_path)309*e5eeaa8eSAndroid Build Coastguard Worker Result<void> GenerateBaseLinkerConfiguration(Context& ctx,
310*e5eeaa8eSAndroid Build Coastguard Worker const std::string& dir_path) {
311*e5eeaa8eSAndroid Build Coastguard Worker return GenerateConfiguration(GetConfiguration(ctx), dir_path, true);
312*e5eeaa8eSAndroid Build Coastguard Worker }
313*e5eeaa8eSAndroid Build Coastguard Worker
GenerateRecoveryLinkerConfiguration(Context & ctx,const std::string & dir_path)314*e5eeaa8eSAndroid Build Coastguard Worker Result<void> GenerateRecoveryLinkerConfiguration(Context& ctx,
315*e5eeaa8eSAndroid Build Coastguard Worker const std::string& dir_path) {
316*e5eeaa8eSAndroid Build Coastguard Worker return GenerateConfiguration(
317*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::contents::CreateRecoveryConfiguration(ctx),
318*e5eeaa8eSAndroid Build Coastguard Worker dir_path,
319*e5eeaa8eSAndroid Build Coastguard Worker false);
320*e5eeaa8eSAndroid Build Coastguard Worker }
321*e5eeaa8eSAndroid Build Coastguard Worker
GenerateApexConfiguration(android::linkerconfig::contents::Context & ctx,const android::linkerconfig::modules::ApexInfo & target_apex,const std::string & base_dir)322*e5eeaa8eSAndroid Build Coastguard Worker Result<void> GenerateApexConfiguration(
323*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::contents::Context& ctx,
324*e5eeaa8eSAndroid Build Coastguard Worker const android::linkerconfig::modules::ApexInfo& target_apex,
325*e5eeaa8eSAndroid Build Coastguard Worker const std::string& base_dir) {
326*e5eeaa8eSAndroid Build Coastguard Worker if (!target_apex.has_bin) {
327*e5eeaa8eSAndroid Build Coastguard Worker return {};
328*e5eeaa8eSAndroid Build Coastguard Worker }
329*e5eeaa8eSAndroid Build Coastguard Worker
330*e5eeaa8eSAndroid Build Coastguard Worker std::string dir_path = base_dir + "/" + target_apex.name;
331*e5eeaa8eSAndroid Build Coastguard Worker if (auto ret = mkdir(dir_path.c_str(), 0755); ret != 0 && errno != EEXIST) {
332*e5eeaa8eSAndroid Build Coastguard Worker return ErrnoError() << "Failed to create directory " << dir_path;
333*e5eeaa8eSAndroid Build Coastguard Worker }
334*e5eeaa8eSAndroid Build Coastguard Worker
335*e5eeaa8eSAndroid Build Coastguard Worker return GenerateConfiguration(
336*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::contents::CreateApexConfiguration(ctx, target_apex),
337*e5eeaa8eSAndroid Build Coastguard Worker dir_path,
338*e5eeaa8eSAndroid Build Coastguard Worker true);
339*e5eeaa8eSAndroid Build Coastguard Worker }
340*e5eeaa8eSAndroid Build Coastguard Worker
GenerateApexConfiguration(android::linkerconfig::contents::Context & ctx,const std::string & apex_name,const std::string & base_dir)341*e5eeaa8eSAndroid Build Coastguard Worker Result<void> GenerateApexConfiguration(
342*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::contents::Context& ctx, const std::string& apex_name,
343*e5eeaa8eSAndroid Build Coastguard Worker const std::string& base_dir) {
344*e5eeaa8eSAndroid Build Coastguard Worker auto end = std::end(ctx.GetApexModules());
345*e5eeaa8eSAndroid Build Coastguard Worker auto it = std::find_if(std::begin(ctx.GetApexModules()),
346*e5eeaa8eSAndroid Build Coastguard Worker end,
347*e5eeaa8eSAndroid Build Coastguard Worker [&apex_name](const auto& apex_info) {
348*e5eeaa8eSAndroid Build Coastguard Worker return apex_info.name == apex_name;
349*e5eeaa8eSAndroid Build Coastguard Worker });
350*e5eeaa8eSAndroid Build Coastguard Worker if (it == end) {
351*e5eeaa8eSAndroid Build Coastguard Worker return Error() << apex_name << " not found.";
352*e5eeaa8eSAndroid Build Coastguard Worker }
353*e5eeaa8eSAndroid Build Coastguard Worker return GenerateApexConfiguration(ctx, *it, base_dir);
354*e5eeaa8eSAndroid Build Coastguard Worker }
355*e5eeaa8eSAndroid Build Coastguard Worker
GenerateApexConfigurations(Context & ctx,const std::string & dir_path)356*e5eeaa8eSAndroid Build Coastguard Worker void GenerateApexConfigurations(Context& ctx, const std::string& dir_path) {
357*e5eeaa8eSAndroid Build Coastguard Worker for (auto const& apex_item : ctx.GetApexModules()) {
358*e5eeaa8eSAndroid Build Coastguard Worker auto result = GenerateApexConfiguration(ctx, apex_item, dir_path);
359*e5eeaa8eSAndroid Build Coastguard Worker if (!result.ok()) {
360*e5eeaa8eSAndroid Build Coastguard Worker LOG(WARNING) << result.error();
361*e5eeaa8eSAndroid Build Coastguard Worker }
362*e5eeaa8eSAndroid Build Coastguard Worker }
363*e5eeaa8eSAndroid Build Coastguard Worker }
364*e5eeaa8eSAndroid Build Coastguard Worker
GenerateApexLibrariesConfig(Context & ctx,const std::string & dir_path)365*e5eeaa8eSAndroid Build Coastguard Worker void GenerateApexLibrariesConfig(Context& ctx, const std::string& dir_path) {
366*e5eeaa8eSAndroid Build Coastguard Worker if (dir_path == "") {
367*e5eeaa8eSAndroid Build Coastguard Worker return;
368*e5eeaa8eSAndroid Build Coastguard Worker }
369*e5eeaa8eSAndroid Build Coastguard Worker const std::string file_path = dir_path + "/apex.libraries.config.txt";
370*e5eeaa8eSAndroid Build Coastguard Worker std::ofstream out(file_path);
371*e5eeaa8eSAndroid Build Coastguard Worker for (auto const& apex_item : ctx.GetApexModules()) {
372*e5eeaa8eSAndroid Build Coastguard Worker if (!apex_item.jni_libs.empty()) {
373*e5eeaa8eSAndroid Build Coastguard Worker out << "jni " << apex_item.namespace_name << " "
374*e5eeaa8eSAndroid Build Coastguard Worker << Join(apex_item.jni_libs, ":") << '\n';
375*e5eeaa8eSAndroid Build Coastguard Worker }
376*e5eeaa8eSAndroid Build Coastguard Worker if (!apex_item.public_libs.empty()) {
377*e5eeaa8eSAndroid Build Coastguard Worker out << "public " << apex_item.namespace_name << " "
378*e5eeaa8eSAndroid Build Coastguard Worker << Join(apex_item.public_libs, ":") << '\n';
379*e5eeaa8eSAndroid Build Coastguard Worker }
380*e5eeaa8eSAndroid Build Coastguard Worker }
381*e5eeaa8eSAndroid Build Coastguard Worker out.close();
382*e5eeaa8eSAndroid Build Coastguard Worker UpdatePermission(file_path);
383*e5eeaa8eSAndroid Build Coastguard Worker }
384*e5eeaa8eSAndroid Build Coastguard Worker
ExitOnFailure(Result<void> task)385*e5eeaa8eSAndroid Build Coastguard Worker void ExitOnFailure(Result<void> task) {
386*e5eeaa8eSAndroid Build Coastguard Worker if (!task.ok()) {
387*e5eeaa8eSAndroid Build Coastguard Worker LOG(FATAL) << task.error();
388*e5eeaa8eSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
389*e5eeaa8eSAndroid Build Coastguard Worker }
390*e5eeaa8eSAndroid Build Coastguard Worker }
391*e5eeaa8eSAndroid Build Coastguard Worker
392*e5eeaa8eSAndroid Build Coastguard Worker #ifdef __ANDROID__
393*e5eeaa8eSAndroid Build Coastguard Worker struct CombinedLogger {
394*e5eeaa8eSAndroid Build Coastguard Worker android::base::LogdLogger logd;
395*e5eeaa8eSAndroid Build Coastguard Worker
operator ()__anon2436d46c0111::CombinedLogger396*e5eeaa8eSAndroid Build Coastguard Worker void operator()(android::base::LogId id, android::base::LogSeverity severity,
397*e5eeaa8eSAndroid Build Coastguard Worker const char* tag, const char* file, unsigned int line,
398*e5eeaa8eSAndroid Build Coastguard Worker const char* message) {
399*e5eeaa8eSAndroid Build Coastguard Worker logd(id, severity, tag, file, line, message);
400*e5eeaa8eSAndroid Build Coastguard Worker KernelLogger(id, severity, tag, file, line, message);
401*e5eeaa8eSAndroid Build Coastguard Worker }
402*e5eeaa8eSAndroid Build Coastguard Worker };
403*e5eeaa8eSAndroid Build Coastguard Worker #endif
404*e5eeaa8eSAndroid Build Coastguard Worker } // namespace
405*e5eeaa8eSAndroid Build Coastguard Worker
main(int argc,char * argv[])406*e5eeaa8eSAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
407*e5eeaa8eSAndroid Build Coastguard Worker android::base::InitLogging(argv
408*e5eeaa8eSAndroid Build Coastguard Worker #ifdef __ANDROID__
409*e5eeaa8eSAndroid Build Coastguard Worker ,
410*e5eeaa8eSAndroid Build Coastguard Worker CombinedLogger()
411*e5eeaa8eSAndroid Build Coastguard Worker #endif
412*e5eeaa8eSAndroid Build Coastguard Worker );
413*e5eeaa8eSAndroid Build Coastguard Worker
414*e5eeaa8eSAndroid Build Coastguard Worker ProgramArgs args = {};
415*e5eeaa8eSAndroid Build Coastguard Worker
416*e5eeaa8eSAndroid Build Coastguard Worker if (!ParseArgs(argc, argv, &args)) {
417*e5eeaa8eSAndroid Build Coastguard Worker PrintUsage(EXIT_FAILURE);
418*e5eeaa8eSAndroid Build Coastguard Worker }
419*e5eeaa8eSAndroid Build Coastguard Worker
420*e5eeaa8eSAndroid Build Coastguard Worker if (android::linkerconfig::modules::IsTreblelizedDevice() &&
421*e5eeaa8eSAndroid Build Coastguard Worker android::linkerconfig::modules::IsVndkLiteDevice()) {
422*e5eeaa8eSAndroid Build Coastguard Worker LOG(ERROR) << "Linkerconfig no longer supports VNDK-Lite configuration";
423*e5eeaa8eSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
424*e5eeaa8eSAndroid Build Coastguard Worker }
425*e5eeaa8eSAndroid Build Coastguard Worker
426*e5eeaa8eSAndroid Build Coastguard Worker LoadVariables(args);
427*e5eeaa8eSAndroid Build Coastguard Worker Context ctx = GetContext(args);
428*e5eeaa8eSAndroid Build Coastguard Worker
429*e5eeaa8eSAndroid Build Coastguard Worker // when exec'ed from init, this is 077, which makes the subdirectories
430*e5eeaa8eSAndroid Build Coastguard Worker // inaccessible for others. set umask to 022 so that they can be
431*e5eeaa8eSAndroid Build Coastguard Worker // accessible.
432*e5eeaa8eSAndroid Build Coastguard Worker umask(022);
433*e5eeaa8eSAndroid Build Coastguard Worker
434*e5eeaa8eSAndroid Build Coastguard Worker if (args.is_recovery) {
435*e5eeaa8eSAndroid Build Coastguard Worker ExitOnFailure(
436*e5eeaa8eSAndroid Build Coastguard Worker GenerateRecoveryLinkerConfiguration(ctx, args.target_directory));
437*e5eeaa8eSAndroid Build Coastguard Worker } else if (args.target_apex != "") {
438*e5eeaa8eSAndroid Build Coastguard Worker ExitOnFailure(GenerateApexConfiguration(
439*e5eeaa8eSAndroid Build Coastguard Worker ctx, args.target_apex, args.target_directory));
440*e5eeaa8eSAndroid Build Coastguard Worker } else {
441*e5eeaa8eSAndroid Build Coastguard Worker ExitOnFailure(GenerateBaseLinkerConfiguration(ctx, args.target_directory));
442*e5eeaa8eSAndroid Build Coastguard Worker GenerateApexConfigurations(ctx, args.target_directory);
443*e5eeaa8eSAndroid Build Coastguard Worker GenerateApexLibrariesConfig(ctx, args.target_directory);
444*e5eeaa8eSAndroid Build Coastguard Worker }
445*e5eeaa8eSAndroid Build Coastguard Worker
446*e5eeaa8eSAndroid Build Coastguard Worker return EXIT_SUCCESS;
447*e5eeaa8eSAndroid Build Coastguard Worker }
448