Home | History | Annotate | Download | only in include
      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