xref: /aosp_15_r20/system/linkerconfig/main.cc (revision e5eeaa8e05bc25a862c0c861bda7c8a6bfb42dad)
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