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 #include "elf_handling.h" 18 19 #include <cxxabi.h> 20 21 using llvm::ELF::ELFDATA2MSB; 22 using llvm::ELF::EM_ARM; 23 using llvm::ELF::EM_MIPS; 24 using llvm::ELF::R_AARCH64_ABS64; 25 using llvm::ELF::R_AARCH64_RELATIVE; 26 using llvm::ELF::R_ARM_ABS32; 27 using llvm::ELF::R_ARM_RELATIVE; 28 using llvm::ELF::R_X86_64_64; 29 using llvm::ELF::R_X86_64_RELATIVE; 30 using llvm::ELF::R_MIPS_64; 31 using llvm::ELF::R_MIPS_REL32; 32 using llvm::ELF::R_MIPS_NONE; 33 using llvm::ELF::SHT_PROGBITS; 34 using llvm::ELF::SHT_REL; 35 using llvm::ELF::SHT_RELA; 36 using llvm::Expected; 37 using llvm::StringRef; 38 using llvm::dyn_cast; 39 using llvm::object::ELF32BEObjectFile; 40 using llvm::object::ELF32LEObjectFile; 41 using llvm::object::ELF64BEObjectFile; 42 using llvm::object::ELF64LEObjectFile; 43 using llvm::object::symbol_iterator; 44 using llvm::support::endian::read; 45 using llvm::outs; 46 using llvm::Error; 47 using llvm::make_unique; 48 49 static std::string demangle(const std::string &MangledName) { 50 char *Str = __cxxabiv1::__cxa_demangle( 51 MangledName.c_str(), 52 nullptr, 53 0, 54 nullptr); 55 if (Str) { 56 std::string DemangledString(Str); 57 free(Str); 58 return DemangledString; 59 } 60 return ""; 61 } 62 63 SharedObject::~SharedObject() {} 64 65 template <typename ELFT> 66 static std::unique_ptr<SharedObject> createELFSharedObject( 67 const ELFObjectFile<ELFT> *Objfile) { 68 return make_unique<ELFSharedObject<ELFT>>(Objfile); 69 } 70 71 static std::unique_ptr<SharedObject>createELFObjFile(const ObjectFile *Obj) { 72 if (const ELF32LEObjectFile *Objfile = dyn_cast<ELF32LEObjectFile>(Obj)) 73 return createELFSharedObject(Objfile); 74 if (const ELF32BEObjectFile *Objfile = dyn_cast<ELF32BEObjectFile>(Obj)) 75 return createELFSharedObject(Objfile); 76 if (const ELF64LEObjectFile *Objfile = dyn_cast<ELF64LEObjectFile>(Obj)) 77 return createELFSharedObject(Objfile); 78 if (const ELF64BEObjectFile *Objfile = dyn_cast<ELF64BEObjectFile>(Obj)) 79 return createELFSharedObject(Objfile); 80 81 return nullptr; 82 } 83 84 std::unique_ptr<SharedObject> SharedObject::create(const ObjectFile *Obj) { 85 std::unique_ptr<SharedObject> res(createELFObjFile(Obj)); 86 if (res && res->getVTables()) { 87 return res; 88 } 89 return nullptr; 90 } 91 92 template <typename ELFT> 93 ELFSharedObject<ELFT>::~ELFSharedObject() {} 94 95 template <typename ELFT> 96 ELFSharedObject<ELFT>::ELFSharedObject( 97 const ELFObjectFile<ELFT> *Objfile) 98 : mObj(Objfile) {} 99 100 template <typename ELFT> 101 bool ELFSharedObject<ELFT>::cacheELFSections() { 102 for (const SectionRef &ElfSection : mObj->sections()) { 103 const Elf_Shdr *ElfShdr = 104 mObj->getSection(ElfSection.getRawDataRefImpl()); 105 if (!ElfShdr) { 106 outs() << "Couldn't create elf shdr \n"; 107 return false; 108 } 109 switch (ElfShdr->sh_type) { 110 case SHT_RELA: 111 case SHT_REL: 112 mRelSectionRefs.emplace_back(ElfSection); 113 break; 114 case SHT_PROGBITS: 115 mProgBitSectionRefs.emplace_back(ElfSection); 116 break; 117 default : 118 // Any other section won't have information pertinent 119 // to vtables. Relocation entries will have the virtual 120 // functions' relocation information, the PROGBITS sections 121 // will have the vtables themselves. 122 break; 123 } 124 } 125 return true; 126 } 127 128 template <typename ELFT> 129 void ELFSharedObject<ELFT>::printVTables() const { 130 for (const VTable &Vtable : mVTables) { 131 if (Vtable.getVTableSize() == 0) 132 continue; 133 outs() << Vtable.getDemangledName() 134 << "\n" 135 << Vtable.getMangledName() 136 << ": " 137 << Vtable.getVTableSize() 138 << " entries" 139 << "\n"; 140 for (const VFunction &Vfunction : Vtable) { 141 outs() << Vfunction.getOffset() 142 << " (int (*)(...)) " 143 << Vfunction.getDemangledName() 144 << "\n"; 145 } 146 outs() << "\n" 147 << "\n"; 148 } 149 } 150 151 template <typename ELFT> 152 bool ELFSharedObject<ELFT>::getVTables() { 153 if (!cacheELFSections()) { 154 return false; 155 } 156 if (!initVTableRanges()) { 157 return true; 158 } 159 getVFunctions(); 160 for (VTable &Vtable : mVTables) { 161 // Sort the functions by offset before displaying them since the order 162 // of functions appearing in relocation sections might change. That 163 // should not result in the vtable layout changing. 164 Vtable.sortVFunctions(); 165 } 166 return true; 167 } 168 169 template <typename ELFT> 170 bool ELFSharedObject<ELFT>::initVTableRanges() { 171 // Go through all the symbols in the dynsym / symtab sections 172 // and cache all the relevant symbols. i.e: symbols which correspond 173 // to either vtables or functions. 174 175 std::vector<std::pair<SymbolRef, uint64_t>> SymsAndSizes = 176 computeSymbolSizes(*mObj); 177 for (std::pair<SymbolRef, uint64_t> &Pair : SymsAndSizes) { 178 SymbolRef Symbol = Pair.first; 179 SymbolRef::Type SymType = UnWrap(Symbol.getType()); 180 uint64_t SymValue = Symbol.getValue(); 181 StringRef SymName = UnWrap(Symbol.getName()); 182 if (SymName.startswith("__ZTV") || SymName.startswith("_ZTV")) { 183 mVTables.emplace_back( 184 SymName.str(), 185 demangle(SymName.str()), 186 Symbol.getValue(), 187 Symbol.getValue() + Pair.second); 188 } else if (SymType == SymbolRef::ST_Function) { 189 std::map<uint64_t, std::vector<SymbolRef>>::iterator It = 190 mAddrToSymbolRef.find(SymValue); 191 if (It == mAddrToSymbolRef.end()) { 192 mAddrToSymbolRef.insert(std::make_pair( 193 SymValue, std::vector<SymbolRef>(1, Symbol))); 194 } else { 195 std::vector<SymbolRef> &SymVec = It->second; 196 SymVec.emplace_back(Symbol); 197 } 198 } 199 } 200 if (mVTables.size() == 0) { 201 return false; 202 } 203 std::sort(mVTables.begin(), mVTables.end()); 204 return true; 205 } 206 207 template <typename ELFT> 208 void ELFSharedObject<ELFT>::getVFunctions() { 209 for (const SectionRef &Section : mRelSectionRefs) { 210 for (const RelocationRef &Relocation : Section.relocations()) { 211 VTable *VtPtr = identifyVTable(Relocation.getOffset()); 212 if (VtPtr != nullptr) { 213 relocateSym(Relocation, Section, VtPtr); 214 } 215 } 216 } 217 } 218 219 template <typename ELFT> 220 VTable *ELFSharedObject<ELFT>::identifyVTable(uint64_t RelOffset) { 221 typename std::vector<VTable>::iterator It; 222 It = std::lower_bound(mVTables.begin(), mVTables.end(), RelOffset); 223 if (It != mVTables.begin() && It->getStartAddr() != RelOffset) { 224 It--; 225 } 226 if (It->getEndAddr() >= RelOffset) { 227 return &(*It); 228 } 229 return nullptr; 230 } 231 232 template <typename ELFT> 233 void ELFSharedObject<ELFT>::relocateSym( 234 const RelocationRef &Relocation, 235 const SectionRef &Section, 236 VTable *Vtablep) { 237 const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader(); 238 if (ElfHeader->e_machine == EM_MIPS) { 239 // bionic/linker/linker_mips.cpp , we handle only one type of 240 // relocation. Depending on if the symbol can be inferred from r_info we 241 // make it an absolute or a relative relocation. 242 if (!absoluteRelocation(Relocation, Vtablep)) { 243 relativeRelocation(Relocation, Section, Vtablep); 244 } 245 } else { 246 switch(Relocation.getType()) { 247 case R_AARCH64_RELATIVE: 248 case R_X86_64_RELATIVE: 249 case R_ARM_RELATIVE: 250 { 251 // The return value is ignored since failure to relocate 252 // does not mean a fatal error. It might be that the dynsym / 253 // symbol-table does not have enough information to get the 254 // symbol name. Like-wise for absolute relocations. 255 relativeRelocation(Relocation, Section, Vtablep); 256 break; 257 } 258 case R_AARCH64_ABS64: 259 case R_X86_64_64: 260 case R_ARM_ABS32: 261 { 262 absoluteRelocation(Relocation, Vtablep); 263 break; 264 } 265 default: 266 break; 267 } 268 } 269 } 270 271 template <typename ELFT> 272 bool ELFSharedObject<ELFT>::absoluteRelocation( 273 const RelocationRef &Relocation, 274 VTable *Vtablep) { 275 symbol_iterator Symi = Relocation.getSymbol(); 276 if (Symi == mObj->symbol_end()) { 277 return false; 278 } 279 SymbolRef Symbol = *Symi; 280 uint64_t RelOffset = Relocation.getOffset(); 281 StringRef SymbolName = UnWrap(Symbol.getName()); 282 std::string DemangledName = demangle(SymbolName.str()); 283 if (!DemangledName.empty()) { 284 Vtablep->addVFunction(SymbolName.str(), DemangledName, RelOffset); 285 return true; 286 } 287 return false; 288 } 289 290 template <typename ELFT> 291 bool ELFSharedObject<ELFT>::relativeRelocation( 292 const RelocationRef &Relocation, 293 const SectionRef &Section, 294 VTable *Vtablep) { 295 uint64_t Addend = 0; 296 uint64_t RelOffset = Relocation.getOffset(); 297 if (mObj->getSection(Section.getRawDataRefImpl())->sh_type == SHT_RELA) { 298 const Elf_Rela *Rela = mObj->getRela(Relocation.getRawDataRefImpl()); 299 Addend = static_cast<uint64_t>(Rela->r_addend); 300 } 301 302 if (Addend == 0) { 303 Addend = identifyAddend(Relocation.getOffset()); 304 } 305 306 std::map<uint64_t, std::vector<SymbolRef>>::iterator It = 307 mAddrToSymbolRef.find(Addend); 308 if (It == mAddrToSymbolRef.end()) { 309 return false; 310 } 311 SymbolRef Symbol = matchValueToSymbol(It->second, Vtablep); 312 StringRef SymbolName = UnWrap(Symbol.getName()); 313 std::string DemangledName = demangle(SymbolName.str()); 314 if (!DemangledName.empty()) { 315 Vtablep->addVFunction(SymbolName.str(), DemangledName, RelOffset); 316 return true; 317 } 318 return false; 319 } 320 321 template <typename ELFT> 322 SymbolRef ELFSharedObject<ELFT>::matchValueToSymbol( 323 std::vector<SymbolRef> &SymVec, 324 VTable *Vtablep) { 325 constexpr size_t pos = sizeof("vtable for ") - 1; 326 const std::string ClassName(Vtablep->getDemangledName().substr(pos)); 327 for (const SymbolRef &Symbol : SymVec) { 328 StringRef SymbolName = UnWrap(Symbol.getName()); 329 if (SymbolName.str().find(ClassName) != std::string::npos) 330 return Symbol; 331 } 332 // Return the 1st Symbol by default. 333 return SymVec[0]; 334 } 335 336 template <typename ELFT> 337 uint64_t ELFSharedObject<ELFT>::identifyAddend(uint64_t ROffset) { 338 for (const SectionRef &Section : mProgBitSectionRefs) { 339 uint64_t Begin = Section.getAddress(); 340 uint64_t End = Section.getAddress() + Section.getSize(); 341 if (ROffset >= Begin && ROffset <= End) { 342 return getAddendFromSection(Section, ROffset - Begin); 343 } 344 } 345 return 0; 346 } 347 348 template <typename ELFT> 349 uint64_t ELFSharedObject<ELFT>::getAddendFromSection( 350 const SectionRef &Section, 351 uint64_t Offset) { 352 StringRef Contents; 353 if (Section.getContents(Contents)) 354 return 0; 355 const unsigned char *Bytes = Contents.bytes_begin() + Offset; 356 uintX_t Addend = read<uintX_t, ELFT::TargetEndianness>(Bytes); 357 const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader(); 358 if (ElfHeader->e_machine == EM_ARM || 359 ElfHeader->e_machine == EM_MIPS) { 360 // Remove thumb flag as llvm suggests. 361 Addend &= ~1; 362 } 363 return static_cast<uint64_t>(Addend); 364 } 365 366 VFunction::VFunction( 367 const std::string &MangledName, 368 const std::string &DemangledName, 369 uint64_t VFunctionOffset) 370 : mMangledName(MangledName), 371 mDemangledName(DemangledName), 372 mOffset(VFunctionOffset) {} 373 374 uint64_t VFunction::getOffset() const { 375 return mOffset; 376 } 377 378 const std::string &VFunction::getDemangledName() const { 379 return mDemangledName; 380 } 381 382 const std::string &VFunction::getMangledName() const { 383 return mMangledName; 384 } 385 386 bool VFunction::operator<(const VFunction &Vfunction) const { 387 return mOffset < Vfunction.getOffset(); 388 } 389 390 VTable::VTable( 391 const std::string &MangledName, 392 const std::string &DemangledName, 393 uint64_t Begin, 394 uint64_t End) 395 : mMangledName(MangledName), 396 mDemangledName(DemangledName), 397 mStartAddr(Begin), 398 mEndAddr(End), 399 mBaseOffset(Begin) {} 400 401 void VTable::addVFunction( 402 const std::string &MangledName, 403 const std::string &DemangledName, 404 uint64_t RelOffset) { 405 mFunctions.emplace_back( 406 MangledName, 407 DemangledName, 408 RelOffset - mBaseOffset); 409 } 410 411 const std::string &VTable::getDemangledName() const { 412 return mDemangledName; 413 } 414 415 const std::string &VTable::getMangledName() const { 416 return mMangledName; 417 } 418 419 uint64_t VTable::getStartAddr() const { 420 return mStartAddr; 421 } 422 423 uint64_t VTable::getEndAddr() const { 424 return mEndAddr; 425 } 426 427 uint64_t VTable::getBaseOffset() const { 428 return mBaseOffset; 429 } 430 431 uint64_t VTable::getVTableSize() const { 432 return mFunctions.size(); 433 } 434 435 VTable::func_iterator VTable::begin() const { 436 return mFunctions.cbegin(); 437 } 438 439 VTable::func_iterator VTable::end() const { 440 return mFunctions.cend(); 441 } 442 443 bool VTable::operator<(const VTable &Vtable) const { 444 return mStartAddr < Vtable.getStartAddr(); 445 } 446 447 bool VTable::operator<(const uint64_t ROffset) const { 448 return mStartAddr < ROffset; 449 } 450 451 void VTable::sortVFunctions() { 452 std::sort(mFunctions.begin(), mFunctions.end()); 453 } 454