• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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