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
FindAndReplace(const std::string & candidate_str,const std::string & find_str,const std::string & replace_str)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;
~SoFileParser()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
ELFSoFileParser(const ELFObjectFile<T> * obj)122 ELFSoFileParser(const ELFObjectFile<T> *obj) : obj_(obj) {}
~ELFSoFileParser()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>
FindRemovedElements(const std::map<K,T> & old_elements_map,const std::map<K,T> & new_elements_map)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>
AddToMap(std::map<K,T> * dst,Iterable & src,KeyGetter get_key,ValueGetter get_value)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>
AddToSet(std::set<K> * dst,Iterable & src,KeyGetter get_key)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>
FindCommonElements(const std::map<K,T> & old_elements_map,const std::map<K,T> & new_elements_map)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