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(bool Mangled) 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 std::string VfunctionName = (Mangled ? 142 Vfunction.getMangledName() : 143 Vfunction.getDemangledName()); 144 outs() << Vfunction.getOffset() 145 << " (int (*)(...)) " 146 << VfunctionName 147 << "\n"; 148 } 149 outs() << "\n" 150 << "\n"; 151 } 152 } 153 154 template <typename ELFT> 155 bool ELFSharedObject<ELFT>::getVTables() { 156 if (!cacheELFSections()) { 157 return false; 158 } 159 if (!initVTableRanges()) { 160 return true; 161 } 162 getVFunctions(); 163 for (VTable &Vtable : mVTables) { 164 // Sort the functions by offset before displaying them since the order 165 // of functions appearing in relocation sections might change. That 166 // should not result in the vtable layout changing. 167 Vtable.sortVFunctions(); 168 } 169 return true; 170 } 171 172 template <typename ELFT> 173 bool ELFSharedObject<ELFT>::initVTableRanges() { 174 // Go through all the symbols in the dynsym / symtab sections 175 // and cache all the relevant symbols. i.e: symbols which correspond 176 // to either vtables or functions. 177 178 std::vector<std::pair<SymbolRef, uint64_t>> SymsAndSizes = 179 computeSymbolSizes(*mObj); 180 for (std::pair<SymbolRef, uint64_t> &Pair : SymsAndSizes) { 181 SymbolRef Symbol = Pair.first; 182 SymbolRef::Type SymType = UnWrap(Symbol.getType()); 183 uint64_t SymValue = Symbol.getValue(); 184 StringRef SymName = UnWrap(Symbol.getName()); 185 if (SymName.startswith("__ZTV") || SymName.startswith("_ZTV")) { 186 mVTables.emplace_back( 187 SymName.str(), 188 demangle(SymName.str()), 189 Symbol.getValue(), 190 Symbol.getValue() + Pair.second); 191 } else if (SymType == SymbolRef::ST_Function) { 192 std::map<uint64_t, std::vector<SymbolRef>>::iterator It = 193 mAddrToSymbolRef.find(SymValue); 194 if (It == mAddrToSymbolRef.end()) { 195 mAddrToSymbolRef.insert(std::make_pair( 196 SymValue, std::vector<SymbolRef>(1, Symbol))); 197 } else { 198 std::vector<SymbolRef> &SymVec = It->second; 199 SymVec.emplace_back(Symbol); 200 } 201 } 202 } 203 if (mVTables.size() == 0) { 204 return false; 205 } 206 std::sort(mVTables.begin(), mVTables.end()); 207 return true; 208 } 209 210 template <typename ELFT> 211 void ELFSharedObject<ELFT>::getVFunctions() { 212 for (const SectionRef &Section : mRelSectionRefs) { 213 for (const RelocationRef &Relocation : Section.relocations()) { 214 VTable *VtPtr = identifyVTable(Relocation.getOffset()); 215 if (VtPtr != nullptr) { 216 relocateSym(Relocation, Section, VtPtr); 217 } 218 } 219 } 220 } 221 222 template <typename ELFT> 223 VTable *ELFSharedObject<ELFT>::identifyVTable(uint64_t RelOffset) { 224 typename std::vector<VTable>::iterator It; 225 It = std::lower_bound(mVTables.begin(), mVTables.end(), RelOffset); 226 if (It != mVTables.begin() && It->getStartAddr() != RelOffset) { 227 It--; 228 } 229 if (It->getEndAddr() >= RelOffset) { 230 return &(*It); 231 } 232 return nullptr; 233 } 234 235 template <typename ELFT> 236 void ELFSharedObject<ELFT>::relocateSym( 237 const RelocationRef &Relocation, 238 const SectionRef &Section, 239 VTable *Vtablep) { 240 const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader(); 241 if (ElfHeader->e_machine == EM_MIPS) { 242 // bionic/linker/linker_mips.cpp , we handle only one type of 243 // relocation. Depending on if the symbol can be inferred from r_info we 244 // make it an absolute or a relative relocation. 245 if (!absoluteRelocation(Relocation, Vtablep)) { 246 relativeRelocation(Relocation, Section, Vtablep); 247 } 248 } else { 249 switch(Relocation.getType()) { 250 case R_AARCH64_RELATIVE: 251 case R_X86_64_RELATIVE: 252 case R_ARM_RELATIVE: 253 { 254 // The return value is ignored since failure to relocate 255 // does not mean a fatal error. It might be that the dynsym / 256 // symbol-table does not have enough information to get the 257 // symbol name. Like-wise for absolute relocations. 258 relativeRelocation(Relocation, Section, Vtablep); 259 break; 260 } 261 case R_AARCH64_ABS64: 262 case R_X86_64_64: 263 case R_ARM_ABS32: 264 { 265 absoluteRelocation(Relocation, Vtablep); 266 break; 267 } 268 default: 269 break; 270 } 271 } 272 } 273 274 template <typename ELFT> 275 bool ELFSharedObject<ELFT>::absoluteRelocation( 276 const RelocationRef &Relocation, 277 VTable *Vtablep) { 278 symbol_iterator Symi = Relocation.getSymbol(); 279 if (Symi == mObj->symbol_end()) { 280 return false; 281 } 282 SymbolRef Symbol = *Symi; 283 uint64_t RelOffset = Relocation.getOffset(); 284 StringRef SymbolName = UnWrap(Symbol.getName()); 285 std::string DemangledName = demangle(SymbolName.str()); 286 if (!DemangledName.empty()) { 287 Vtablep->addVFunction(SymbolName.str(), DemangledName, RelOffset); 288 return true; 289 } 290 return false; 291 } 292 293 template <typename ELFT> 294 bool ELFSharedObject<ELFT>::relativeRelocation( 295 const RelocationRef &Relocation, 296 const SectionRef &Section, 297 VTable *Vtablep) { 298 uint64_t Addend = 0; 299 uint64_t RelOffset = Relocation.getOffset(); 300 if (mObj->getSection(Section.getRawDataRefImpl())->sh_type == SHT_RELA) { 301 const Elf_Rela *Rela = mObj->getRela(Relocation.getRawDataRefImpl()); 302 Addend = static_cast<uint64_t>(Rela->r_addend); 303 } 304 305 if (Addend == 0) { 306 Addend = identifyAddend(Relocation.getOffset()); 307 } 308 309 std::map<uint64_t, std::vector<SymbolRef>>::iterator It = 310 mAddrToSymbolRef.find(Addend); 311 if (It == mAddrToSymbolRef.end()) { 312 return false; 313 } 314 SymbolRef Symbol = matchValueToSymbol(It->second, Vtablep); 315 StringRef SymbolName = UnWrap(Symbol.getName()); 316 std::string DemangledName = demangle(SymbolName.str()); 317 if (!DemangledName.empty()) { 318 Vtablep->addVFunction(SymbolName.str(), DemangledName, RelOffset); 319 return true; 320 } 321 return false; 322 } 323 324 template <typename ELFT> 325 SymbolRef ELFSharedObject<ELFT>::matchValueToSymbol( 326 std::vector<SymbolRef> &SymVec, 327 VTable *Vtablep) { 328 constexpr size_t pos = sizeof("vtable for ") - 1; 329 const std::string ClassName(Vtablep->getDemangledName().substr(pos)); 330 for (const SymbolRef &Symbol : SymVec) { 331 StringRef SymbolName = UnWrap(Symbol.getName()); 332 if (demangle(SymbolName.str()).find(ClassName) != std::string::npos) { 333 return Symbol; 334 } 335 } 336 // Return the 1st Symbol by default. 337 return SymVec[0]; 338 } 339 340 template <typename ELFT> 341 uint64_t ELFSharedObject<ELFT>::identifyAddend(uint64_t ROffset) { 342 for (const SectionRef &Section : mProgBitSectionRefs) { 343 uint64_t Begin = Section.getAddress(); 344 uint64_t End = Section.getAddress() + Section.getSize(); 345 if (ROffset >= Begin && ROffset <= End) { 346 return getAddendFromSection(Section, ROffset - Begin); 347 } 348 } 349 return 0; 350 } 351 352 template <typename ELFT> 353 uint64_t ELFSharedObject<ELFT>::getAddendFromSection( 354 const SectionRef &Section, 355 uint64_t Offset) { 356 StringRef Contents; 357 if (Section.getContents(Contents)) 358 return 0; 359 const unsigned char *Bytes = Contents.bytes_begin() + Offset; 360 uintX_t Addend = read<uintX_t, ELFT::TargetEndianness>(Bytes); 361 const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader(); 362 if (ElfHeader->e_machine == EM_ARM || 363 ElfHeader->e_machine == EM_MIPS) { 364 // Remove thumb flag as llvm suggests. 365 Addend &= ~1; 366 } 367 return static_cast<uint64_t>(Addend); 368 } 369 370 VFunction::VFunction( 371 const std::string &MangledName, 372 const std::string &DemangledName, 373 uint64_t VFunctionOffset) 374 : mMangledName(MangledName), 375 mDemangledName(DemangledName), 376 mOffset(VFunctionOffset) {} 377 378 uint64_t VFunction::getOffset() const { 379 return mOffset; 380 } 381 382 const std::string &VFunction::getDemangledName() const { 383 return mDemangledName; 384 } 385 386 const std::string &VFunction::getMangledName() const { 387 return mMangledName; 388 } 389 390 bool VFunction::operator<(const VFunction &Vfunction) const { 391 return mOffset < Vfunction.getOffset(); 392 } 393 394 VTable::VTable( 395 const std::string &MangledName, 396 const std::string &DemangledName, 397 uint64_t Begin, 398 uint64_t End) 399 : mMangledName(MangledName), 400 mDemangledName(DemangledName), 401 mStartAddr(Begin), 402 mEndAddr(End), 403 mBaseOffset(Begin) {} 404 405 void VTable::addVFunction( 406 const std::string &MangledName, 407 const std::string &DemangledName, 408 uint64_t RelOffset) { 409 mFunctions.emplace_back( 410 MangledName, 411 DemangledName, 412 RelOffset - mBaseOffset); 413 } 414 415 const std::string &VTable::getDemangledName() const { 416 return mDemangledName; 417 } 418 419 const std::string &VTable::getMangledName() const { 420 return mMangledName; 421 } 422 423 uint64_t VTable::getStartAddr() const { 424 return mStartAddr; 425 } 426 427 uint64_t VTable::getEndAddr() const { 428 return mEndAddr; 429 } 430 431 uint64_t VTable::getBaseOffset() const { 432 return mBaseOffset; 433 } 434 435 uint64_t VTable::getVTableSize() const { 436 return mFunctions.size(); 437 } 438 439 VTable::func_iterator VTable::begin() const { 440 return mFunctions.cbegin(); 441 } 442 443 VTable::func_iterator VTable::end() const { 444 return mFunctions.cend(); 445 } 446 447 bool VTable::operator<(const VTable &Vtable) const { 448 return mStartAddr < Vtable.getStartAddr(); 449 } 450 451 bool VTable::operator<(const uint64_t ROffset) const { 452 return mStartAddr < ROffset; 453 } 454 455 void VTable::sortVFunctions() { 456 std::sort(mFunctions.begin(), mFunctions.end()); 457 } 458