xref: /aosp_15_r20/system/linkerconfig/generator/librarylistloader.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 "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