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 "linkerconfig/librarylistloader.h"
18*e5eeaa8eSAndroid Build Coastguard Worker
19*e5eeaa8eSAndroid Build Coastguard Worker #include <android-base/result.h>
20*e5eeaa8eSAndroid Build Coastguard Worker #include <android-base/strings.h>
21*e5eeaa8eSAndroid Build Coastguard Worker #include <algorithm>
22*e5eeaa8eSAndroid Build Coastguard Worker #include <fstream>
23*e5eeaa8eSAndroid Build Coastguard Worker #include <iterator>
24*e5eeaa8eSAndroid Build Coastguard Worker #include <set>
25*e5eeaa8eSAndroid Build Coastguard Worker #include <sstream>
26*e5eeaa8eSAndroid Build Coastguard Worker #include <unordered_map>
27*e5eeaa8eSAndroid Build Coastguard Worker
28*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/environment.h"
29*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/log.h"
30*e5eeaa8eSAndroid Build Coastguard Worker
31*e5eeaa8eSAndroid Build Coastguard Worker using LibraryList = std::set<std::string>;
32*e5eeaa8eSAndroid Build Coastguard Worker
33*e5eeaa8eSAndroid Build Coastguard Worker using android::base::Result;
34*e5eeaa8eSAndroid Build Coastguard Worker
35*e5eeaa8eSAndroid Build Coastguard Worker namespace {
36*e5eeaa8eSAndroid Build Coastguard Worker std::unordered_map<std::string, LibraryList> library_file_cache;
GetLibrariesFromFile(std::string file_path)37*e5eeaa8eSAndroid Build Coastguard Worker Result<LibraryList> GetLibrariesFromFile(std::string file_path) {
38*e5eeaa8eSAndroid Build Coastguard Worker auto cached_data = library_file_cache.find(file_path);
39*e5eeaa8eSAndroid Build Coastguard Worker if (cached_data != library_file_cache.end()) {
40*e5eeaa8eSAndroid Build Coastguard Worker return cached_data->second;
41*e5eeaa8eSAndroid Build Coastguard Worker }
42*e5eeaa8eSAndroid Build Coastguard Worker
43*e5eeaa8eSAndroid Build Coastguard Worker std::string library_name;
44*e5eeaa8eSAndroid Build Coastguard Worker LibraryList library_list;
45*e5eeaa8eSAndroid Build Coastguard Worker std::ifstream library_file(file_path.c_str(), std::ifstream::in);
46*e5eeaa8eSAndroid Build Coastguard Worker
47*e5eeaa8eSAndroid Build Coastguard Worker if (!library_file) {
48*e5eeaa8eSAndroid Build Coastguard Worker return ErrnoErrorf("Failed to open file {}", file_path);
49*e5eeaa8eSAndroid Build Coastguard Worker }
50*e5eeaa8eSAndroid Build Coastguard Worker
51*e5eeaa8eSAndroid Build Coastguard Worker while (std::getline(library_file, library_name)) {
52*e5eeaa8eSAndroid Build Coastguard Worker library_name = android::base::Trim(library_name);
53*e5eeaa8eSAndroid Build Coastguard Worker if (!library_name.empty()) {
54*e5eeaa8eSAndroid Build Coastguard Worker library_list.insert(library_name);
55*e5eeaa8eSAndroid Build Coastguard Worker }
56*e5eeaa8eSAndroid Build Coastguard Worker }
57*e5eeaa8eSAndroid Build Coastguard Worker
58*e5eeaa8eSAndroid Build Coastguard Worker library_file_cache.insert({file_path, library_list});
59*e5eeaa8eSAndroid Build Coastguard Worker
60*e5eeaa8eSAndroid Build Coastguard Worker return library_list;
61*e5eeaa8eSAndroid Build Coastguard Worker }
62*e5eeaa8eSAndroid Build Coastguard Worker } // namespace
63*e5eeaa8eSAndroid Build Coastguard Worker
64*e5eeaa8eSAndroid Build Coastguard Worker namespace android {
65*e5eeaa8eSAndroid Build Coastguard Worker namespace linkerconfig {
66*e5eeaa8eSAndroid Build Coastguard Worker namespace generator {
GetLibrariesString(const std::string & library_file_path)67*e5eeaa8eSAndroid Build Coastguard Worker std::string GetLibrariesString(const std::string& library_file_path) {
68*e5eeaa8eSAndroid Build Coastguard Worker auto library_list_result = GetLibrariesFromFile(library_file_path);
69*e5eeaa8eSAndroid Build Coastguard Worker if (library_list_result.ok()) {
70*e5eeaa8eSAndroid Build Coastguard Worker return android::base::Join(*library_list_result, ':');
71*e5eeaa8eSAndroid Build Coastguard Worker } else {
72*e5eeaa8eSAndroid Build Coastguard Worker // Consider unavailable library file as empty
73*e5eeaa8eSAndroid Build Coastguard Worker LOG(WARNING) << library_list_result.error();
74*e5eeaa8eSAndroid Build Coastguard Worker return "";
75*e5eeaa8eSAndroid Build Coastguard Worker }
76*e5eeaa8eSAndroid Build Coastguard Worker }
77*e5eeaa8eSAndroid Build Coastguard Worker
GetPublicLibrariesString(const std::string & library_file_path,const std::string & private_library_file_path)78*e5eeaa8eSAndroid Build Coastguard Worker std::string GetPublicLibrariesString(
79*e5eeaa8eSAndroid Build Coastguard Worker const std::string& library_file_path,
80*e5eeaa8eSAndroid Build Coastguard Worker const std::string& private_library_file_path) {
81*e5eeaa8eSAndroid Build Coastguard Worker auto library_list = GetLibrariesFromFile(library_file_path);
82*e5eeaa8eSAndroid Build Coastguard Worker auto private_library_list = GetLibrariesFromFile(private_library_file_path);
83*e5eeaa8eSAndroid Build Coastguard Worker
84*e5eeaa8eSAndroid Build Coastguard Worker if (!library_list.ok()) {
85*e5eeaa8eSAndroid Build Coastguard Worker // Consider unavailable library file as empty
86*e5eeaa8eSAndroid Build Coastguard Worker LOG(WARNING) << library_list.error();
87*e5eeaa8eSAndroid Build Coastguard Worker return "";
88*e5eeaa8eSAndroid Build Coastguard Worker }
89*e5eeaa8eSAndroid Build Coastguard Worker
90*e5eeaa8eSAndroid Build Coastguard Worker if (!private_library_list.ok()) {
91*e5eeaa8eSAndroid Build Coastguard Worker // No private library found. All libraries are public
92*e5eeaa8eSAndroid Build Coastguard Worker LOG(WARNING) << private_library_list.error();
93*e5eeaa8eSAndroid Build Coastguard Worker return android::base::Join(*library_list, ':');
94*e5eeaa8eSAndroid Build Coastguard Worker }
95*e5eeaa8eSAndroid Build Coastguard Worker
96*e5eeaa8eSAndroid Build Coastguard Worker LibraryList public_library_list;
97*e5eeaa8eSAndroid Build Coastguard Worker
98*e5eeaa8eSAndroid Build Coastguard Worker std::set_difference(
99*e5eeaa8eSAndroid Build Coastguard Worker library_list->begin(),
100*e5eeaa8eSAndroid Build Coastguard Worker library_list->end(),
101*e5eeaa8eSAndroid Build Coastguard Worker private_library_list->begin(),
102*e5eeaa8eSAndroid Build Coastguard Worker private_library_list->end(),
103*e5eeaa8eSAndroid Build Coastguard Worker std::inserter(public_library_list, public_library_list.begin()));
104*e5eeaa8eSAndroid Build Coastguard Worker
105*e5eeaa8eSAndroid Build Coastguard Worker return android::base::Join(public_library_list, ':');
106*e5eeaa8eSAndroid Build Coastguard Worker }
107*e5eeaa8eSAndroid Build Coastguard Worker
GetPrivateLibrariesString(const std::string & library_file_path,const std::string & private_library_file_path)108*e5eeaa8eSAndroid Build Coastguard Worker std::string GetPrivateLibrariesString(
109*e5eeaa8eSAndroid Build Coastguard Worker const std::string& library_file_path,
110*e5eeaa8eSAndroid Build Coastguard Worker const std::string& private_library_file_path) {
111*e5eeaa8eSAndroid Build Coastguard Worker auto library_list = GetLibrariesFromFile(library_file_path);
112*e5eeaa8eSAndroid Build Coastguard Worker auto private_library_list = GetLibrariesFromFile(private_library_file_path);
113*e5eeaa8eSAndroid Build Coastguard Worker
114*e5eeaa8eSAndroid Build Coastguard Worker if (!library_list.ok()) {
115*e5eeaa8eSAndroid Build Coastguard Worker // Consider unavailable library file as empty
116*e5eeaa8eSAndroid Build Coastguard Worker LOG(WARNING) << library_list.error();
117*e5eeaa8eSAndroid Build Coastguard Worker return "";
118*e5eeaa8eSAndroid Build Coastguard Worker }
119*e5eeaa8eSAndroid Build Coastguard Worker
120*e5eeaa8eSAndroid Build Coastguard Worker if (!private_library_list.ok()) {
121*e5eeaa8eSAndroid Build Coastguard Worker // No private library found. All libraries are public
122*e5eeaa8eSAndroid Build Coastguard Worker LOG(WARNING) << private_library_list.error();
123*e5eeaa8eSAndroid Build Coastguard Worker return "";
124*e5eeaa8eSAndroid Build Coastguard Worker }
125*e5eeaa8eSAndroid Build Coastguard Worker
126*e5eeaa8eSAndroid Build Coastguard Worker LibraryList private_only_library_list;
127*e5eeaa8eSAndroid Build Coastguard Worker
128*e5eeaa8eSAndroid Build Coastguard Worker std::set_intersection(library_list->begin(),
129*e5eeaa8eSAndroid Build Coastguard Worker library_list->end(),
130*e5eeaa8eSAndroid Build Coastguard Worker private_library_list->begin(),
131*e5eeaa8eSAndroid Build Coastguard Worker private_library_list->end(),
132*e5eeaa8eSAndroid Build Coastguard Worker std::inserter(private_only_library_list,
133*e5eeaa8eSAndroid Build Coastguard Worker private_only_library_list.begin()));
134*e5eeaa8eSAndroid Build Coastguard Worker
135*e5eeaa8eSAndroid Build Coastguard Worker return android::base::Join(private_only_library_list, ':');
136*e5eeaa8eSAndroid Build Coastguard Worker }
137*e5eeaa8eSAndroid Build Coastguard Worker } // namespace generator
138*e5eeaa8eSAndroid Build Coastguard Worker } // namespace linkerconfig
139*e5eeaa8eSAndroid Build Coastguard Worker } // namespace android
140