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 switch (Sec.sh_type) { 45 case SHT_SYMTAB: 46 Symtab = &Sec; 47 break; 48 case SHT_STRTAB: 49 case SHT_NULL: 50 case SHT_RELA: 51 case SHT_REL: 52 break; 53 default: 54 auto *C = new (Alloc) SectionChunk<ELFT>(this->getObj(), &Sec); 55 Chunks.push_back(C); 56 break; 57 } 58 } 59 } 60 61 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() { 62 ErrorOr<StringRef> StringTableOrErr = 63 ELFObj->getStringTableForSymtab(*Symtab); 64 error(StringTableOrErr.getError()); 65 StringRef StringTable = *StringTableOrErr; 66 67 Elf_Sym_Range Syms = ELFObj->symbols(Symtab); 68 uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); 69 uint32_t FirstNonLocal = Symtab->sh_info; 70 if (FirstNonLocal > NumSymbols) 71 error("Invalid sh_info in symbol table"); 72 Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end()); 73 SymbolBodies.reserve(NumSymbols); 74 for (const Elf_Sym &Sym : Syms) 75 SymbolBodies.push_back(createSymbolBody(StringTable, &Sym)); 76 } 77 78 template <class ELFT> 79 SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, 80 const Elf_Sym *Sym) { 81 ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable); 82 error(NameOrErr.getError()); 83 StringRef Name = *NameOrErr; 84 switch (Sym->getBinding()) { 85 default: 86 error("unexpected binding"); 87 case STB_GLOBAL: 88 if (Sym->isUndefined()) 89 return new (Alloc) Undefined(Name); 90 return new (Alloc) DefinedRegular(Name); 91 case STB_WEAK: 92 if (Sym->isUndefined()) 93 return new (Alloc) UndefinedWeak(Name); 94 return new (Alloc) DefinedWeak(Name); 95 } 96 } 97 98 namespace lld { 99 namespace elf2 { 100 template class elf2::ObjectFile<llvm::object::ELF32LE>; 101 template class elf2::ObjectFile<llvm::object::ELF32BE>; 102 template class elf2::ObjectFile<llvm::object::ELF64LE>; 103 template class elf2::ObjectFile<llvm::object::ELF64BE>; 104 } 105 } 106