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)35 static 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() const47 const std::set<std::string> &ELFSoFileParser<T>::GetFunctions() const {
48   return functions_;
49 }
50 
51 template<typename T>
GetGlobVars() const52 const std::set<std::string> &ELFSoFileParser<T>::GetGlobVars() const {
53   return globvars_;
54 }
55 
56 template<typename T>
IsSymbolExported(const Elf_Sym * elf_sym) const57 bool 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()68 void 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)88 static 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)93 std::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