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