1 //===- InputFiles.cpp -----------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "InputFiles.h" 11 #include "Chunks.h" 12 #include "Error.h" 13 #include "Symbols.h" 14 #include "llvm/ADT/STLExtras.h" 15 16 using namespace llvm::ELF; 17 18 using namespace lld; 19 using namespace lld::elf2; 20 21 template <class ELFT> 22 bool ObjectFile<ELFT>::isCompatibleWith(const ObjectFileBase &Other) const { 23 if (kind() != Other.kind()) 24 return false; 25 return getObj()->getHeader()->e_machine == 26 cast<ObjectFile<ELFT>>(Other).getObj()->getHeader()->e_machine; 27 } 28 29 template <class ELFT> void elf2::ObjectFile<ELFT>::parse() { 30 // Parse a memory buffer as a ELF file. 31 std::error_code EC; 32 ELFObj = llvm::make_unique<ELFFile<ELFT>>(MB.getBuffer(), EC); 33 error(EC); 34 35 // Read section and symbol tables. 36 initializeChunks(); 37 initializeSymbols(); 38 } 39 40 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeChunks() { 41 uint64_t Size = ELFObj->getNumSections(); 42 Chunks.reserve(Size); 43 for (const Elf_Shdr &Sec : ELFObj->sections()) { 44 if (Sec.sh_type == SHT_SYMTAB) { 45 Symtab = &Sec; 46 continue; 47 } 48 if (Sec.sh_flags & SHF_ALLOC) { 49 auto *C = new (Alloc) SectionChunk<ELFT>(this->getObj(), &Sec); 50 Chunks.push_back(C); 51 } 52 } 53 } 54 55 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() { 56 ErrorOr<StringRef> StringTableOrErr = 57 ELFObj->getStringTableForSymtab(*Symtab); 58 error(StringTableOrErr.getError()); 59 StringRef StringTable = *StringTableOrErr; 60 61 Elf_Sym_Range Syms = ELFObj->symbols(Symtab); 62 uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); 63 uint32_t FirstNonLocal = Symtab->sh_info; 64 if (FirstNonLocal > NumSymbols) 65 error("Invalid sh_info in symbol table"); 66 Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end()); 67 SymbolBodies.reserve(NumSymbols); 68 for (const Elf_Sym &Sym : Syms) 69 SymbolBodies.push_back(createSymbolBody(StringTable, &Sym)); 70 } 71 72 template <class ELFT> 73 SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, 74 const Elf_Sym *Sym) { 75 ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable); 76 error(NameOrErr.getError()); 77 StringRef Name = *NameOrErr; 78 switch (Sym->getBinding()) { 79 default: 80 error("unexpected binding"); 81 case STB_GLOBAL: 82 if (Sym->isUndefined()) 83 return new (Alloc) Undefined(Name); 84 return new (Alloc) DefinedRegular(Name); 85 case STB_WEAK: 86 if (Sym->isUndefined()) 87 return new (Alloc) UndefinedWeak(Name); 88 return new (Alloc) DefinedWeak(Name); 89 } 90 } 91 92 namespace lld { 93 namespace elf2 { 94 template class elf2::ObjectFile<llvm::object::ELF32LE>; 95 template class elf2::ObjectFile<llvm::object::ELF32BE>; 96 template class elf2::ObjectFile<llvm::object::ELF64LE>; 97 template class elf2::ObjectFile<llvm::object::ELF64BE>; 98 } 99 } 100