OSDN Git Service

Merge "Make inline tcsetattr definition match constants."
[android-x86/bionic.git] / linker / linker_config.cpp
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include "linker_config.h"
30
31 #include "linker_globals.h"
32 #include "linker_debug.h"
33 #include "linker_utils.h"
34
35 #include <android-base/file.h>
36 #include <android-base/scopeguard.h>
37 #include <android-base/strings.h>
38
39 #include <async_safe/log.h>
40
41 #include <stdlib.h>
42
43 #include <string>
44 #include <unordered_map>
45
46 class ConfigParser {
47  public:
48   enum {
49     kProperty,
50     kSection,
51     kEndOfFile,
52     kError,
53   };
54
55   explicit ConfigParser(std::string&& content)
56       : content_(content), p_(0), lineno_(0), was_end_of_file_(false) {}
57
58   /*
59    * Possible return values
60    * kProperty: name is set to property name and value is set to property value
61    * kSection: name is set to section name.
62    * kEndOfFile: reached end of file.
63    * kError: error_msg is set.
64    */
65   int next_token(std::string* name, std::string* value, std::string* error_msg) {
66     std::string line;
67     while(NextLine(&line)) {
68       size_t found = line.find('#');
69       line = android::base::Trim(line.substr(0, found));
70
71       if (line.empty()) {
72         continue;
73       }
74
75       if (line[0] == '[' && line[line.size() - 1] == ']') {
76         *name = line.substr(1, line.size() - 2);
77         return kSection;
78       }
79
80       found = line.find('=');
81       if (found == std::string::npos) {
82         *error_msg = std::string("invalid format: ") +
83                     line +
84                     ", expected \"name = property\" or \"[section]\"";
85         return kError;
86       }
87
88       *name = android::base::Trim(line.substr(0, found));
89       *value = android::base::Trim(line.substr(found + 1));
90       return kProperty;
91     }
92
93     // to avoid infinite cycles when programmer makes a mistake
94     CHECK(!was_end_of_file_);
95     was_end_of_file_ = true;
96     return kEndOfFile;
97   }
98
99   size_t lineno() const {
100     return lineno_;
101   }
102
103  private:
104   bool NextLine(std::string* line) {
105     if (p_ == std::string::npos) {
106       return false;
107     }
108
109     size_t found = content_.find('\n', p_);
110     if (found != std::string::npos) {
111       *line = content_.substr(p_, found - p_);
112       p_ = found + 1;
113     } else {
114       *line = content_.substr(p_);
115       p_ = std::string::npos;
116     }
117
118     lineno_++;
119     return true;
120   }
121
122   std::string content_;
123   size_t p_;
124   size_t lineno_;
125   bool was_end_of_file_;
126
127   DISALLOW_IMPLICIT_CONSTRUCTORS(ConfigParser);
128 };
129
130 class PropertyValue {
131  public:
132   PropertyValue() = default;
133
134   PropertyValue(std::string&& value, size_t lineno)
135     : value_(value), lineno_(lineno) {}
136
137   const std::string& value() const {
138     return value_;
139   }
140
141   size_t lineno() const {
142     return lineno_;
143   }
144
145  private:
146   std::string value_;
147   size_t lineno_;
148 };
149
150 static std::string create_error_msg(const char* file,
151                                     size_t lineno,
152                                     const std::string& msg) {
153   char buf[1024];
154   async_safe_format_buffer(buf, sizeof(buf), "%s:%zu: error: %s", file, lineno, msg.c_str());
155
156   return std::string(buf);
157 }
158
159 static bool parse_config_file(const char* ld_config_file_path,
160                               const char* binary_realpath,
161                               std::unordered_map<std::string, PropertyValue>* properties,
162                               std::string* error_msg) {
163   std::string content;
164   if (!android::base::ReadFileToString(ld_config_file_path, &content)) {
165     if (errno != ENOENT) {
166       *error_msg = std::string("error reading file \"") +
167                    ld_config_file_path + "\": " + strerror(errno);
168     }
169     return false;
170   }
171
172   ConfigParser cp(std::move(content));
173
174   std::string section_name;
175
176   while(true) {
177     std::string name;
178     std::string value;
179     std::string error;
180
181     int result = cp.next_token(&name, &value, &error);
182     if (result == ConfigParser::kError) {
183       DL_WARN("error parsing %s:%zd: %s (ignoring this line)",
184               ld_config_file_path,
185               cp.lineno(),
186               error.c_str());
187       continue;
188     }
189
190     if (result == ConfigParser::kSection || result == ConfigParser::kEndOfFile) {
191       return false;
192     }
193
194     if (result == ConfigParser::kProperty) {
195       if (!android::base::StartsWith(name, "dir.")) {
196         DL_WARN("error parsing %s:%zd: unexpected property name \"%s\", "
197                 "expected format dir.<section_name> (ignoring this line)",
198                 ld_config_file_path,
199                 cp.lineno(),
200                 name.c_str());
201         continue;
202       }
203
204       // remove trailing '/'
205       while (value[value.size() - 1] == '/') {
206         value = value.substr(0, value.size() - 1);
207       }
208
209       if (value.empty()) {
210         DL_WARN("error parsing %s:%zd: property value is empty (ignoring this line)",
211                 ld_config_file_path,
212                 cp.lineno());
213         continue;
214       }
215
216       if (file_is_under_dir(binary_realpath, value)) {
217         section_name = name.substr(4);
218         break;
219       }
220     }
221   }
222
223   // skip everything until we meet a correct section
224   while (true) {
225     std::string name;
226     std::string value;
227     std::string error;
228
229     int result = cp.next_token(&name, &value, &error);
230
231     if (result == ConfigParser::kSection && name == section_name) {
232       break;
233     }
234
235     if (result == ConfigParser::kEndOfFile) {
236       *error_msg = create_error_msg(ld_config_file_path,
237                                     cp.lineno(),
238                                     std::string("section \"") + section_name + "\" not found");
239       return false;
240     }
241   }
242
243   // found the section - parse it
244   while (true) {
245     std::string name;
246     std::string value;
247     std::string error;
248
249     int result = cp.next_token(&name, &value, &error);
250
251     if (result == ConfigParser::kEndOfFile || result == ConfigParser::kSection) {
252       break;
253     }
254
255     if (result == ConfigParser::kProperty) {
256       if (properties->find(name) != properties->end()) {
257         DL_WARN("%s:%zd: warning: property \"%s\" redefinition",
258                 ld_config_file_path,
259                 cp.lineno(),
260                 name.c_str());
261       }
262
263       (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
264     }
265
266     if (result == ConfigParser::kError) {
267       DL_WARN("error parsing %s:%zd: %s (ignoring this line)",
268               ld_config_file_path,
269               cp.lineno(),
270               error.c_str());
271       continue;
272     }
273   }
274
275   return true;
276 }
277
278 static Config g_config;
279
280 static constexpr const char* kDefaultConfigName = "default";
281 static constexpr const char* kPropertyAdditionalNamespaces = "additional.namespaces";
282 #if defined(__LP64__)
283 static constexpr const char* kLibParamValue = "lib64";
284 #else
285 static constexpr const char* kLibParamValue = "lib";
286 #endif
287
288 class Properties {
289  public:
290   explicit Properties(std::unordered_map<std::string, PropertyValue>&& properties)
291       : properties_(properties), target_sdk_version_(__ANDROID_API__) {}
292
293   std::vector<std::string> get_strings(const std::string& name, size_t* lineno = nullptr) const {
294     auto it = find_property(name, lineno);
295     if (it == properties_.end()) {
296       // return empty vector
297       return std::vector<std::string>();
298     }
299
300     std::vector<std::string> strings = android::base::Split(it->second.value(), ",");
301
302     for (size_t i = 0; i < strings.size(); ++i) {
303       strings[i] = android::base::Trim(strings[i]);
304     }
305
306     return strings;
307   }
308
309   bool get_bool(const std::string& name, size_t* lineno = nullptr) const {
310     auto it = find_property(name, lineno);
311     if (it == properties_.end()) {
312       return false;
313     }
314
315     return it->second.value() == "true";
316   }
317
318   std::string get_string(const std::string& name, size_t* lineno = nullptr) const {
319     auto it = find_property(name, lineno);
320     return (it == properties_.end()) ? "" : it->second.value();
321   }
322
323   std::vector<std::string> get_paths(const std::string& name, size_t* lineno = nullptr) {
324     std::string paths_str = get_string(name, lineno);
325
326     std::vector<std::string> paths;
327     split_path(paths_str.c_str(), ":", &paths);
328
329     std::vector<std::pair<std::string, std::string>> params;
330     params.push_back({ "LIB", kLibParamValue });
331     if (target_sdk_version_ != 0) {
332       char buf[16];
333       async_safe_format_buffer(buf, sizeof(buf), "%d", target_sdk_version_);
334       params.push_back({ "SDK_VER", buf });
335     }
336
337     for (auto&& path : paths) {
338       format_string(&path, params);
339     }
340
341     std::vector<std::string> resolved_paths;
342
343     // do not remove paths that do not exist
344     resolve_paths(paths, &resolved_paths);
345
346     return resolved_paths;
347   }
348
349   void set_target_sdk_version(int target_sdk_version) {
350     target_sdk_version_ = target_sdk_version;
351   }
352
353  private:
354   std::unordered_map<std::string, PropertyValue>::const_iterator
355   find_property(const std::string& name, size_t* lineno) const {
356     auto it = properties_.find(name);
357     if (it != properties_.end() && lineno != nullptr) {
358       *lineno = it->second.lineno();
359     }
360
361     return it;
362   }
363   std::unordered_map<std::string, PropertyValue> properties_;
364   int target_sdk_version_;
365
366   DISALLOW_IMPLICIT_CONSTRUCTORS(Properties);
367 };
368
369 bool Config::read_binary_config(const char* ld_config_file_path,
370                                       const char* binary_realpath,
371                                       bool is_asan,
372                                       const Config** config,
373                                       std::string* error_msg) {
374   // TODO(b/38114603) Currently, multiple namespaces does not support ASAN mode
375   // where some symbols should be intercepted via LD_PRELOAD; LD_PRELOADed libs
376   // are not being preloaded into the linked namespaces other than the default
377   // namespace. Until we fix the problem, we temporarily disable ld.config.txt
378   // in ASAN mode.
379   if (is_asan) {
380     return false;
381   }
382
383   g_config.clear();
384
385   std::unordered_map<std::string, PropertyValue> property_map;
386   if (!parse_config_file(ld_config_file_path, binary_realpath, &property_map, error_msg)) {
387     return false;
388   }
389
390   Properties properties(std::move(property_map));
391
392   auto failure_guard = android::base::make_scope_guard([] { g_config.clear(); });
393
394   std::unordered_map<std::string, NamespaceConfig*> namespace_configs;
395
396   namespace_configs[kDefaultConfigName] = g_config.create_namespace_config(kDefaultConfigName);
397
398   std::vector<std::string> additional_namespaces = properties.get_strings(kPropertyAdditionalNamespaces);
399   for (const auto& name : additional_namespaces) {
400     namespace_configs[name] = g_config.create_namespace_config(name);
401   }
402
403   bool versioning_enabled = properties.get_bool("enable.target.sdk.version");
404   int target_sdk_version = __ANDROID_API__;
405   if (versioning_enabled) {
406     std::string version_file = dirname(binary_realpath) + "/.version";
407     std::string content;
408     if (!android::base::ReadFileToString(version_file, &content)) {
409       if (errno != ENOENT) {
410         *error_msg = std::string("error reading version file \"") +
411                      version_file + "\": " + strerror(errno);
412         return false;
413       }
414     } else {
415       content = android::base::Trim(content);
416       errno = 0;
417       char* end = nullptr;
418       const char* content_str = content.c_str();
419       int result = strtol(content_str, &end, 10);
420       if (errno == 0 && *end == '\0' && result > 0) {
421         target_sdk_version = result;
422         properties.set_target_sdk_version(target_sdk_version);
423       } else {
424         *error_msg = std::string("invalid version \"") + version_file + "\": \"" + content +"\"";
425         return false;
426       }
427     }
428   }
429
430   g_config.set_target_sdk_version(target_sdk_version);
431
432   for (auto ns_config_it : namespace_configs) {
433     auto& name = ns_config_it.first;
434     NamespaceConfig* ns_config = ns_config_it.second;
435
436     std::string property_name_prefix = std::string("namespace.") + name;
437
438     size_t lineno = 0;
439     std::vector<std::string> linked_namespaces =
440         properties.get_strings(property_name_prefix + ".links", &lineno);
441
442     for (const auto& linked_ns_name : linked_namespaces) {
443       if (namespace_configs.find(linked_ns_name) == namespace_configs.end()) {
444         *error_msg = create_error_msg(ld_config_file_path,
445                                       lineno,
446                                       std::string("undefined namespace: ") + linked_ns_name);
447         return false;
448       }
449
450       std::string shared_libs = properties.get_string(property_name_prefix +
451                                                       ".link." +
452                                                       linked_ns_name +
453                                                       ".shared_libs", &lineno);
454
455       if (shared_libs.empty()) {
456         *error_msg = create_error_msg(ld_config_file_path,
457                                       lineno,
458                                       std::string("list of shared_libs for ") +
459                                       name +
460                                       "->" +
461                                       linked_ns_name +
462                                       " link is not specified or is empty.");
463         return false;
464       }
465
466       ns_config->add_namespace_link(linked_ns_name, shared_libs);
467     }
468
469     ns_config->set_isolated(properties.get_bool(property_name_prefix + ".isolated"));
470     ns_config->set_visible(properties.get_bool(property_name_prefix + ".visible"));
471
472     // these are affected by is_asan flag
473     if (is_asan) {
474       property_name_prefix += ".asan";
475     }
476
477     ns_config->set_search_paths(properties.get_paths(property_name_prefix + ".search.paths"));
478     ns_config->set_permitted_paths(properties.get_paths(property_name_prefix + ".permitted.paths"));
479   }
480
481   failure_guard.Disable();
482   *config = &g_config;
483   return true;
484 }
485
486 NamespaceConfig* Config::create_namespace_config(const std::string& name) {
487   namespace_configs_.push_back(std::unique_ptr<NamespaceConfig>(new NamespaceConfig(name)));
488   NamespaceConfig* ns_config_ptr = namespace_configs_.back().get();
489   namespace_configs_map_[name] = ns_config_ptr;
490   return ns_config_ptr;
491 }
492
493 void Config::clear() {
494   namespace_configs_.clear();
495   namespace_configs_map_.clear();
496 }