1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ELF_HANDLING_H_ 18 #define ELF_HANDLING_H_ 19 20 #include <map> 21 #include <memory> 22 #include <string> 23 #include <system_error> 24 #include <vector> 25 26 #include <llvm/Object/ELFObjectFile.h> 27 #include <llvm/Object/ELFTypes.h> 28 #include <llvm/Object/SymbolSize.h> 29 #include <llvm/Support/Endian.h> 30 #include <llvm/Support/raw_ostream.h> 31 32 using llvm::object::ObjectFile; 33 using llvm::object::ELFObjectFile; 34 using llvm::object::SectionRef; 35 using llvm::object::RelocationRef; 36 using llvm::object::ELFFile; 37 using llvm::object::ELFType; 38 using llvm::object::ELFDataTypeTypedefHelper; 39 using llvm::object::SymbolRef; 40 using llvm::outs; 41 42 class SharedObject { 43 public: 44 static std::unique_ptr<SharedObject> create(const ObjectFile *); 45 virtual void printVTables() const = 0; 46 virtual ~SharedObject() = 0; 47 private: 48 virtual bool getVTables() = 0; 49 }; 50 51 class VFunction { 52 public: 53 VFunction( 54 const std::string &, 55 const std::string &, 56 uint64_t); 57 58 uint64_t getOffset() const; 59 bool operator<(const VFunction &) const; 60 const std::string &getMangledName() const; 61 const std::string &getDemangledName() const; 62 private: 63 std::string mMangledName; 64 std::string mDemangledName; 65 uint64_t mOffset; 66 }; 67 68 class VTable { 69 public: 70 using func_iterator = std::vector<VFunction>::const_iterator; 71 VTable( 72 const std::string &, 73 const std::string &, 74 uint64_t, 75 uint64_t); 76 77 uint64_t getStartAddr() const; 78 uint64_t getEndAddr() const; 79 uint64_t getBaseOffset() const; 80 uint64_t getVTableSize() const; 81 func_iterator begin() const; 82 func_iterator end() const; 83 const std::string &getMangledName() const; 84 const std::string &getDemangledName() const; 85 void sortVFunctions(); 86 void addVFunction( 87 const std::string &, 88 const std::string &, 89 uint64_t); 90 91 bool operator<(const VTable &) const; 92 bool operator<(const uint64_t) const; 93 private: 94 std::vector<VFunction> mFunctions; 95 std::string mMangledName; 96 std::string mDemangledName; 97 /* This holds the range(st_value, st_value) through which the 98 * VTable spans. 99 */ 100 uint64_t mStartAddr; 101 uint64_t mEndAddr; 102 uint64_t mBaseOffset; 103 }; 104 105 template<typename ELFT> 106 class ELFSharedObject : public SharedObject { 107 public: 108 void printVTables() const override; 109 bool getVTables() override; 110 ~ELFSharedObject(); 111 ELFSharedObject(const ELFObjectFile<ELFT> *); 112 113 private: 114 /* We need a sym value to SymbolRef map in case the relocation provides 115 * us with an addr instead of a sym index into dynsym / symtab. 116 */ 117 LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 118 typedef ELFFile<ELFT> ELFO; 119 typedef typename ELFO::Elf_Shdr Elf_Shdr; 120 typedef typename ELFO::Elf_Ehdr Elf_Ehdr; 121 typedef typename ELFO::Elf_Sym Elf_Sym; 122 typedef typename ELFO::Elf_Rela Elf_Rela; 123 typedef typename ELFO::uintX_t uintX_t; 124 std::map<uint64_t, std::vector<SymbolRef>> mAddrToSymbolRef; 125 const ELFObjectFile<ELFT> *mObj; 126 /* We cache the relocation sections, to look through their relocations for 127 * vfunctions. Sections with type SHT_PROGBITS are cached since they contain 128 * vtables. We might need to peek at the contents of a vtable in cases of 129 * relative relocations. 130 */ 131 std::vector<SectionRef> mRelSectionRefs; 132 std::vector<SectionRef> mProgBitSectionRefs; 133 std::vector<VTable> mVTables; 134 135 private: 136 bool cacheELFSections(); 137 bool initVTableRanges(); 138 void getVFunctions(); 139 VTable *identifyVTable(uint64_t); 140 void relocateSym( 141 const RelocationRef &, 142 const SectionRef &, 143 VTable *); 144 145 bool absoluteRelocation(const RelocationRef &, VTable *); 146 bool relativeRelocation( 147 const RelocationRef &, 148 const SectionRef &, 149 VTable *); 150 151 uint64_t identifyAddend(uint64_t); 152 uint64_t getAddendFromSection(const SectionRef &, uint64_t); 153 SymbolRef matchValueToSymbol(std::vector<SymbolRef> &, VTable *); 154 }; 155 156 template <typename T> 157 static inline T UnWrap(llvm::Expected<T> ValueOrError) { 158 if (!ValueOrError) { 159 outs() << "\nError: " 160 << llvm::toString(ValueOrError.takeError()) 161 << ".\n"; 162 outs().flush(); 163 exit(1); 164 } 165 return std::move(ValueOrError.get()); 166 } 167 168 169 #endif // ELF_HANDLING_H_ 170