blob: 4f08cf4b42da822929e5c48f5c67d09c35fefb6f [file] [log] [blame]
Kiyoung Kime9a77fe2019-05-23 11:04:20 +09001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Kiyoung Kime6558072019-09-30 16:58:39 +090016
Jooyung Han471aeb92020-02-20 18:21:03 +090017#include <climits>
18#include <cstdlib>
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090019#include <cstring>
20#include <fstream>
21#include <iostream>
22#include <string>
23
Jooyung Hana59fbd52020-01-30 12:57:34 +090024#include <errno.h>
Kiyoung Kim5c8366d2019-12-30 18:43:00 +090025#include <fcntl.h>
Jooyung Han471aeb92020-02-20 18:21:03 +090026#include <getopt.h>
Kiyoung Kim5c8366d2019-12-30 18:43:00 +090027#include <sys/stat.h>
Jooyung Hana59fbd52020-01-30 12:57:34 +090028#include <sys/types.h>
Kiyoung Kim5c8366d2019-12-30 18:43:00 +090029
Jooyung Han471aeb92020-02-20 18:21:03 +090030#include <android-base/result.h>
31
Kiyoung Kim284bc722020-01-20 13:33:00 +090032#include "linkerconfig/apex.h"
33#include "linkerconfig/apexconfig.h"
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090034#include "linkerconfig/baseconfig.h"
Kiyoung Kim284bc722020-01-20 13:33:00 +090035#include "linkerconfig/context.h"
Kiyoung Kime6558072019-09-30 16:58:39 +090036#include "linkerconfig/environment.h"
37#include "linkerconfig/legacy.h"
Kiyoung Kim853438d2019-07-16 09:51:14 +090038#include "linkerconfig/log.h"
Jooyung Han9960aca2020-02-06 20:17:53 +090039#include "linkerconfig/namespacebuilder.h"
Kiyoung Kim09cbb082019-12-05 16:44:34 +090040#include "linkerconfig/recovery.h"
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090041#include "linkerconfig/variableloader.h"
Jooyung Hana3d5d092019-09-26 23:23:50 +090042#include "linkerconfig/variables.h"
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090043
Kiyoung Kim5c8366d2019-12-30 18:43:00 +090044using android::base::ErrnoError;
45using android::base::Error;
46using android::base::Result;
Jooyung Han87e7df82020-02-03 14:23:06 +090047using android::linkerconfig::contents::Context;
Kiyoung Kim284bc722020-01-20 13:33:00 +090048using android::linkerconfig::modules::ApexInfo;
Kiyoung Kim5c8366d2019-12-30 18:43:00 +090049using android::linkerconfig::modules::Configuration;
50
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090051namespace {
52const static struct option program_options[] = {
53 {"target", required_argument, 0, 't'},
Jooyung Hanb4af7472020-02-03 18:07:12 +090054 {"strict", no_argument, 0, 's'},
Josh Gao76614bb2019-12-11 15:28:30 -080055#ifndef __ANDROID__
Jooyung Hana3d5d092019-09-26 23:23:50 +090056 {"root", required_argument, 0, 'r'},
57 {"vndk", required_argument, 0, 'v'},
Kiyoung Kim722dad62019-12-19 15:59:55 +090058 {"recovery", no_argument, 0, 'y'},
Jooyung Han5bbb1232019-12-23 13:35:00 +090059 {"legacy", no_argument, 0, 'l'},
Jooyung Hana3d5d092019-09-26 23:23:50 +090060#endif
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090061 {"help", no_argument, 0, 'h'},
62 {0, 0, 0, 0}};
63
64struct ProgramArgs {
Kiyoung Kim5c8366d2019-12-30 18:43:00 +090065 std::string target_directory;
Jooyung Hanb4af7472020-02-03 18:07:12 +090066 bool strict;
Jooyung Hana3d5d092019-09-26 23:23:50 +090067 std::string root;
68 std::string vndk_version;
Kiyoung Kim722dad62019-12-19 15:59:55 +090069 bool is_recovery;
Jooyung Han5bbb1232019-12-23 13:35:00 +090070 bool is_legacy;
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090071};
72
73[[noreturn]] void PrintUsage(int status = EXIT_SUCCESS) {
Kiyoung Kim5c8366d2019-12-30 18:43:00 +090074 std::cerr << "Usage : linkerconfig [--target <target_directory>]"
Jooyung Hanb4af7472020-02-03 18:07:12 +090075 " [--strict]"
Jooyung Hana3d5d092019-09-26 23:23:50 +090076#ifndef __ANDROID__
77 " --root <root dir>"
78 " --vndk <vndk version>"
Kiyoung Kim722dad62019-12-19 15:59:55 +090079 " --recovery"
Jooyung Han5bbb1232019-12-23 13:35:00 +090080 " --legacy"
Jooyung Hana3d5d092019-09-26 23:23:50 +090081#endif
82 " [--help]"
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090083 << std::endl;
84 exit(status);
85}
86
Jooyung Han471aeb92020-02-20 18:21:03 +090087std::string RealPath(std::string_view path) {
88 char resolved_path[PATH_MAX];
89 if (realpath(path.data(), resolved_path) != nullptr) {
90 return resolved_path;
91 }
92 PrintUsage(-1);
93}
94
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090095bool ParseArgs(int argc, char* argv[], ProgramArgs* args) {
96 int parse_result;
Jooyung Hana3d5d092019-09-26 23:23:50 +090097 while ((parse_result = getopt_long(
Jooyung Hanb4af7472020-02-03 18:07:12 +090098 argc, argv, "t:sr:v:hyl", program_options, NULL)) != -1) {
Kiyoung Kime9a77fe2019-05-23 11:04:20 +090099 switch (parse_result) {
100 case 't':
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900101 args->target_directory = optarg;
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900102 break;
Jooyung Hanb4af7472020-02-03 18:07:12 +0900103 case 's':
104 args->strict = true;
105 break;
Jooyung Hana3d5d092019-09-26 23:23:50 +0900106 case 'r':
Jooyung Han471aeb92020-02-20 18:21:03 +0900107 args->root = RealPath(optarg);
Jooyung Hana3d5d092019-09-26 23:23:50 +0900108 break;
109 case 'v':
110 args->vndk_version = optarg;
111 break;
Kiyoung Kim722dad62019-12-19 15:59:55 +0900112 case 'y':
113 args->is_recovery = true;
114 break;
Jooyung Han5bbb1232019-12-23 13:35:00 +0900115 case 'l':
116 args->is_legacy = true;
117 break;
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900118 case 'h':
119 PrintUsage();
120 default:
121 return false;
122 }
123 }
124
125 if (optind < argc) {
126 return false;
127 }
128
129 return true;
130}
131
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900132void LoadVariables(ProgramArgs args) {
Kiyoung Kim722dad62019-12-19 15:59:55 +0900133#ifndef __ANDROID__
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900134 if (!args.is_recovery && (args.root == "" || args.vndk_version == "")) {
Kiyoung Kim722dad62019-12-19 15:59:55 +0900135 PrintUsage();
136 }
137 android::linkerconfig::modules::Variables::AddValue("ro.vndk.version",
138 args.vndk_version);
139#endif
140
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900141 if (!args.is_recovery) {
142 android::linkerconfig::generator::LoadVariables(args.root);
143 }
144}
Kiyoung Kim722dad62019-12-19 15:59:55 +0900145
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900146Result<void> WriteConfigurationToFile(Configuration& conf,
147 std::string file_path) {
148 std::ostream* out = &std::cout;
149 std::ofstream file_out;
150
151 if (file_path != "") {
152 file_out.open(file_path);
153 if (file_out.fail()) {
154 return ErrnoError() << "Failed to open file " << file_path;
155 }
156 out = &file_out;
157 }
158
159 android::linkerconfig::modules::ConfigWriter config_writer;
160
161 conf.WriteConfig(config_writer);
162 *out << config_writer.ToString();
163 if (!out->good()) {
164 return ErrnoError() << "Failed to write content to " << file_path;
165 }
166
167 return {};
168}
169
Jooyung Han5f246362020-01-28 15:44:14 +0900170Result<void> UpdatePermission([[maybe_unused]] const std::string& file_path) {
171#ifdef __ANDROID__
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900172 if (fchmodat(AT_FDCWD,
173 file_path.c_str(),
174 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
175 AT_SYMLINK_NOFOLLOW) < 0) {
176 return ErrnoError() << "Failed to update permission of " << file_path;
177 }
Jooyung Han5f246362020-01-28 15:44:14 +0900178#endif
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900179
180 return {};
181}
182
Jooyung Han87e7df82020-02-03 14:23:06 +0900183Context GetContext(ProgramArgs args) {
Jooyung Han471aeb92020-02-20 18:21:03 +0900184 auto apex_list = android::linkerconfig::modules::ScanActiveApexes(args.root);
Jooyung Han87e7df82020-02-03 14:23:06 +0900185 Context ctx;
186 for (auto const& apex_item : apex_list) {
187 auto apex_info = apex_item.second;
188 if (apex_info.has_bin || apex_info.has_lib) {
189 ctx.AddApexModule(std::move(apex_info));
190 }
191 }
Jooyung Hanb4af7472020-02-03 18:07:12 +0900192 if (args.strict) {
193 ctx.SetStrictMode(true);
194 }
Jooyung Han9960aca2020-02-06 20:17:53 +0900195 android::linkerconfig::contents::RegisterApexNamespaceBuilders(ctx);
Jooyung Han87e7df82020-02-03 14:23:06 +0900196 return ctx;
197}
198
199Configuration GetConfiguration(Context& ctx) {
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900200 if (android::linkerconfig::modules::IsRecoveryMode()) {
Jooyung Han87e7df82020-02-03 14:23:06 +0900201 return android::linkerconfig::contents::CreateRecoveryConfiguration(ctx);
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900202 }
203
204 if (android::linkerconfig::modules::IsLegacyDevice()) {
Jooyung Han87e7df82020-02-03 14:23:06 +0900205 return android::linkerconfig::contents::CreateLegacyConfiguration(ctx);
Kiyoung Kime6558072019-09-30 16:58:39 +0900206 }
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900207
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900208 // Use base configuration in default
Jooyung Han87e7df82020-02-03 14:23:06 +0900209 return android::linkerconfig::contents::CreateBaseConfiguration(ctx);
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900210}
Kiyoung Kime3bad042019-07-23 13:38:34 +0900211
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900212Result<void> GenerateConfiguration(Configuration config, std::string dir_path,
213 bool update_permission) {
214 std::string file_path = "";
215 if (dir_path != "") {
216 file_path = dir_path + "/ld.config.txt";
217 }
218
219 auto write_config = WriteConfigurationToFile(config, file_path);
Bernie Innocenti5c325562020-02-06 23:16:23 +0900220 if (!write_config.ok()) {
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900221 return write_config;
222 } else if (update_permission && file_path != "") {
223 return UpdatePermission(file_path);
224 }
225
226 return {};
227}
228
Jooyung Han87e7df82020-02-03 14:23:06 +0900229Result<void> GenerateBaseLinkerConfiguration(Context& ctx,
230 const std::string& dir_path) {
231 return GenerateConfiguration(GetConfiguration(ctx), dir_path, true);
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900232}
233
Jooyung Han87e7df82020-02-03 14:23:06 +0900234Result<void> GenerateRecoveryLinkerConfiguration(Context& ctx,
235 const std::string& dir_path) {
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900236 return GenerateConfiguration(
Jooyung Han87e7df82020-02-03 14:23:06 +0900237 android::linkerconfig::contents::CreateRecoveryConfiguration(ctx),
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900238 dir_path,
239 false);
240}
241
Jooyung Han87e7df82020-02-03 14:23:06 +0900242Result<void> GenerateLegacyLinkerConfiguration(Context& ctx,
243 const std::string& dir_path) {
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900244 return GenerateConfiguration(
Jooyung Han87e7df82020-02-03 14:23:06 +0900245 android::linkerconfig::contents::CreateLegacyConfiguration(ctx),
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900246 dir_path,
247 false);
248}
249
Kiyoung Kim284bc722020-01-20 13:33:00 +0900250Result<void> GenerateApexConfiguration(
251 const std::string& base_dir, android::linkerconfig::contents::Context& ctx,
252 const android::linkerconfig::modules::ApexInfo& target_apex) {
253 std::string dir_path = base_dir + "/" + target_apex.name;
Jooyung Hana59fbd52020-01-30 12:57:34 +0900254 if (auto ret = mkdir(dir_path.c_str(), 0755); ret != 0 && errno != EEXIST) {
Kiyoung Kim284bc722020-01-20 13:33:00 +0900255 return ErrnoError() << "Failed to create directory " << dir_path;
256 }
257
258 return GenerateConfiguration(
259 android::linkerconfig::contents::CreateApexConfiguration(ctx, target_apex),
260 dir_path,
261 true);
262}
263
Jooyung Han87e7df82020-02-03 14:23:06 +0900264void GenerateApexConfigurations(Context& ctx, const std::string& dir_path) {
265 for (auto const& apex_item : ctx.GetApexModules()) {
266 if (apex_item.has_bin) {
267 auto result = GenerateApexConfiguration(dir_path, ctx, apex_item);
Bernie Innocenti5c325562020-02-06 23:16:23 +0900268 if (!result.ok()) {
Kiyoung Kim284bc722020-01-20 13:33:00 +0900269 LOG(WARNING) << result.error();
270 }
271 }
272 }
273}
274
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900275void ExitOnFailure(Result<void> task) {
Bernie Innocenti5c325562020-02-06 23:16:23 +0900276 if (!task.ok()) {
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900277 LOG(FATAL) << task.error();
278 exit(EXIT_FAILURE);
279 }
280}
281
Jooyung Hana3d5d092019-09-26 23:23:50 +0900282#ifdef __ANDROID__
Kiyoung Kime3bad042019-07-23 13:38:34 +0900283struct CombinedLogger {
284 android::base::LogdLogger logd;
285
286 void operator()(android::base::LogId id, android::base::LogSeverity severity,
287 const char* tag, const char* file, unsigned int line,
288 const char* message) {
289 logd(id, severity, tag, file, line, message);
290 KernelLogger(id, severity, tag, file, line, message);
291 }
292};
Jooyung Hana3d5d092019-09-26 23:23:50 +0900293#endif
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900294} // namespace
295
296int main(int argc, char* argv[]) {
Jooyung Hana3d5d092019-09-26 23:23:50 +0900297 android::base::InitLogging(argv
298#ifdef __ANDROID__
299 ,
300 CombinedLogger()
301#endif
302 );
Kiyoung Kime3bad042019-07-23 13:38:34 +0900303
Jooyung Han5bbb1232019-12-23 13:35:00 +0900304 ProgramArgs args = {};
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900305
306 if (!ParseArgs(argc, argv, &args)) {
307 PrintUsage(EXIT_FAILURE);
308 }
309
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900310 LoadVariables(args);
Jooyung Han87e7df82020-02-03 14:23:06 +0900311 Context ctx = GetContext(args);
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900312
Jiyong Parkd6018202020-02-21 13:56:52 +0900313 // when exec'ed from init, this is 0x0077, which makes the subdirectories
314 // inaccessible for others. set umask to 0x0022 so that they can be
315 // accessible.
316 umask(0x0022);
317
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900318 if (args.is_recovery) {
Jooyung Han87e7df82020-02-03 14:23:06 +0900319 ExitOnFailure(
320 GenerateRecoveryLinkerConfiguration(ctx, args.target_directory));
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900321 } else if (args.is_legacy) {
Jooyung Han87e7df82020-02-03 14:23:06 +0900322 ExitOnFailure(GenerateLegacyLinkerConfiguration(ctx, args.target_directory));
Kiyoung Kim5c8366d2019-12-30 18:43:00 +0900323 } else {
Jooyung Han87e7df82020-02-03 14:23:06 +0900324 ExitOnFailure(GenerateBaseLinkerConfiguration(ctx, args.target_directory));
325 GenerateApexConfigurations(ctx, args.target_directory);
Kiyoung Kime9a77fe2019-05-23 11:04:20 +0900326 }
327
328 return EXIT_SUCCESS;
Josh Gao76614bb2019-12-11 15:28:30 -0800329}