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 <header_abi_util.h> 16 17 #include <llvm/Object/ELFObjectFile.h> 18 #include <llvm/Object/Binary.h> 19 #include <llvm/Object/ELFTypes.h> 20 #include <llvm/Object/SymbolSize.h> 21 22 using llvm::object::ELF32LEObjectFile; 23 using llvm::object::ELF32BEObjectFile; 24 using llvm::object::ELF64LEObjectFile; 25 using llvm::object::ELF64BEObjectFile; 26 using llvm::dyn_cast; 27 using llvm::ELF::STV_DEFAULT; 28 using llvm::ELF::STV_PROTECTED; 29 using llvm::ELF::STB_WEAK; 30 using llvm::ELF::STB_GLOBAL; 31 32 namespace abi_util { 33 34 template <typename T> UnWrap(llvm::Expected<T> ValueOrError)35static inline T UnWrap(llvm::Expected<T> ValueOrError) { 36 if (!ValueOrError) { 37 llvm::errs() << "\nError: " 38 << llvm::toString(ValueOrError.takeError()) 39 << ".\n"; 40 llvm::errs().flush(); 41 exit(1); 42 } 43 return std::move(ValueOrError.get()); 44 } 45 46 template<typename T> GetFunctions() const47const std::set<std::string> &ELFSoFileParser<T>::GetFunctions() const { 48 return functions_; 49 } 50 51 template<typename T> GetGlobVars() const52const std::set<std::string> &ELFSoFileParser<T>::GetGlobVars() const { 53 return globvars_; 54 } 55 56 template<typename T> IsSymbolExported(const Elf_Sym * elf_sym) const57bool ELFSoFileParser<T>::IsSymbolExported(const Elf_Sym *elf_sym) const { 58 59 unsigned char visibility = elf_sym->getVisibility(); 60 unsigned char binding = elf_sym->getBinding(); 61 62 return (binding == STB_GLOBAL || binding == STB_WEAK) && 63 (visibility == STV_DEFAULT || 64 visibility == STV_PROTECTED); 65 } 66 67 template<typename T> GetSymbols()68void ELFSoFileParser<T>::GetSymbols() { 69 assert(obj_ != nullptr); 70 for (auto symbol_it : obj_->symbols()) { 71 const Elf_Sym *elf_sym = 72 obj_->getSymbol(symbol_it.getRawDataRefImpl()); 73 assert (elf_sym != nullptr); 74 if (!IsSymbolExported(elf_sym) || elf_sym->isUndefined()) { 75 continue; 76 } 77 llvm::object::SymbolRef::Type type = UnWrap(symbol_it.getType()); 78 std::string symbol_name = UnWrap(symbol_it.getName()); 79 if (type == llvm::object::SymbolRef::Type::ST_Function) { 80 functions_.insert(symbol_name); 81 } else if (type == llvm::object::SymbolRef::Type::ST_Data) { 82 globvars_.insert(symbol_name); 83 } 84 } 85 } 86 87 template<typename T> CreateELFSoFileParser(const llvm::object::ELFObjectFile<T> * elfo)88static std::unique_ptr<SoFileParser> CreateELFSoFileParser( 89 const llvm::object::ELFObjectFile<T> *elfo) { 90 return llvm::make_unique<ELFSoFileParser<T>>(elfo); 91 } 92 Create(const llvm::object::ObjectFile * objfile)93std::unique_ptr<SoFileParser> SoFileParser::Create( 94 const llvm::object::ObjectFile *objfile) { 95 // Little-endian 32-bit 96 if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(objfile)) { 97 return CreateELFSoFileParser(ELFObj); 98 } 99 100 // Big-endian 32-bit 101 if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(objfile)) { 102 return CreateELFSoFileParser(ELFObj); 103 } 104 105 // Little-endian 64-bit 106 if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(objfile)) { 107 return CreateELFSoFileParser(ELFObj); 108 } 109 110 // Big-endian 64-bit 111 if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(objfile)) { 112 return CreateELFSoFileParser(ELFObj); 113 } 114 return nullptr; 115 } 116 117 } // namespace abi_util 118 119