1 // Copyright (C) 2017 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <llvm/Object/ELFObjectFile.h> 16 #include <llvm/Object/ELFTypes.h> 17 #include <llvm/Object/SymbolSize.h> 18 #include <llvm/Support/Endian.h> 19 #include <llvm/Support/raw_ostream.h> 20 21 #include <map> 22 #include <regex> 23 #include <set> 24 #include <string> 25 #include <vector> 26 27 using llvm::object::ObjectFile; 28 using llvm::object::ELFObjectFile; 29 using llvm::object::ELFFile; 30 using llvm::object::ELFType; 31 using llvm::object::ELFDataTypeTypedefHelper; 32 33 namespace abi_util { 34 35 std::string RealPath(const std::string &path); 36 37 std::set<std::string> CollectAllExportedHeaders( 38 const std::vector<std::string> &exported_header_dirs); 39 40 class VersionScriptParser { 41 public: 42 43 enum LineScope { 44 global, 45 local, 46 }; 47 48 VersionScriptParser(const std::string &version_script, 49 const std::string &arch, 50 const std::string &api); 51 bool Parse(); 52 53 const std::set<std::string> &GetFunctions(); 54 55 const std::set<std::string> &GetGlobVars(); 56 57 const std::set<std::string> &GetFunctionRegexs(); 58 59 const std::set<std::string> &GetGlobVarRegexs(); 60 61 private: 62 63 bool ParseInnerBlock(std::ifstream &symbol_ifstream); 64 65 LineScope GetLineScope(std::string &line, LineScope scope); 66 67 bool ParseSymbolLine(const std::string &line); 68 69 bool SymbolInArchAndApiVersion(const std::string &line, 70 const std::string &arch, int api); 71 72 bool SymbolExported(const std::string &line, const std::string &arch, 73 int api); 74 75 int ApiStrToInt(const std::string &api); 76 77 void AddToVars(std::string &symbol); 78 79 void AddToFunctions(std::string &symbol); 80 81 private: 82 const std::string &version_script_; 83 const std::string &arch_; 84 std::set<std::string> functions_; 85 std::set<std::string> globvars_; 86 // Added to speed up version script parsing and linking. 87 std::set<std::string> function_regexs_; 88 std::set<std::string> globvar_regexs_; 89 int api_; 90 }; 91 92 inline std::string FindAndReplace(const std::string &candidate_str, 93 const std::string &find_str, 94 const std::string &replace_str) { 95 // Find all matches of find_str in candidate_str and return a new string with 96 // all the matches replaced with replace_str 97 std::regex match_expr(find_str); 98 return std::regex_replace(candidate_str, match_expr, replace_str); 99 } 100 101 102 class SoFileParser { 103 public: 104 static std::unique_ptr<SoFileParser> Create(const ObjectFile *obj); 105 virtual const std::set<std::string> &GetFunctions() const = 0; 106 virtual const std::set<std::string> &GetGlobVars() const = 0; 107 virtual ~SoFileParser() {}; 108 virtual void GetSymbols() = 0; 109 }; 110 111 template<typename T> 112 class ELFSoFileParser : public SoFileParser { 113 public: 114 const std::set<std::string> &GetFunctions() const override; 115 116 const std::set<std::string> &GetGlobVars() const override; 117 118 LLVM_ELF_IMPORT_TYPES_ELFT(T) 119 typedef ELFFile<T> ELFO; 120 typedef typename ELFO::Elf_Sym Elf_Sym; 121 122 ELFSoFileParser(const ELFObjectFile<T> *obj) : obj_(obj) {} 123 virtual ~ELFSoFileParser() override {}; 124 void GetSymbols() override; 125 private: 126 const ELFObjectFile<T> *obj_; 127 std::set<std::string> functions_; 128 std::set<std::string> globvars_; 129 130 private: 131 bool IsSymbolExported(const Elf_Sym *elf_sym) const; 132 }; 133 134 template <typename T, typename K> 135 std::vector<T> FindRemovedElements( 136 const std::map<K, T> &old_elements_map, 137 const std::map<K, T> &new_elements_map) { 138 std::vector<T> removed_elements; 139 for (auto &&map_element : old_elements_map) { 140 auto element_key = map_element.first; 141 auto new_element = new_elements_map.find(element_key); 142 if (new_element == new_elements_map.end()) { 143 removed_elements.emplace_back(map_element.second); 144 } 145 } 146 return removed_elements; 147 } 148 149 template <typename K, typename T, typename Iterable, typename KeyGetter, 150 typename ValueGetter> 151 inline void AddToMap(std::map<K, T> *dst, Iterable &src, KeyGetter get_key, 152 ValueGetter get_value) { 153 for (auto &&element : src) { 154 dst->insert(std::make_pair(get_key(&element), get_value(&element))); 155 } 156 } 157 158 template <typename K, typename Iterable, typename KeyGetter> 159 inline void AddToSet(std::set<K> *dst, Iterable &src, KeyGetter get_key) { 160 for (auto &&element : src) { 161 dst->insert(get_key(element)); 162 } 163 } 164 165 template <typename K, typename T> 166 std::vector<std::pair<T, T>> FindCommonElements( 167 const std::map<K, T> &old_elements_map, 168 const std::map<K, T> &new_elements_map) { 169 std::vector<std::pair<T, T>> common_elements; 170 typename std::map<K, T>::const_iterator old_element = 171 old_elements_map.begin(); 172 typename std::map<K, T>::const_iterator new_element = 173 new_elements_map.begin(); 174 while (old_element != old_elements_map.end() && 175 new_element != new_elements_map.end()) { 176 if (old_element->first == new_element->first) { 177 common_elements.emplace_back(std::make_pair( 178 old_element->second, new_element->second)); 179 old_element++; 180 new_element++; 181 continue; 182 } 183 if (old_element->first < new_element->first) { 184 old_element++; 185 } else { 186 new_element++; 187 } 188 } 189 return common_elements; 190 } 191 192 } // namespace abi_util 193