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.resize(Size); 43 unsigned I = 0; 44 for (const Elf_Shdr &Sec : ELFObj->sections()) { 45 switch (Sec.sh_type) { 46 case SHT_SYMTAB: 47 Symtab = &Sec; 48 break; 49 case SHT_SYMTAB_SHNDX: { 50 ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = ELFObj->getSHNDXTable(Sec); 51 error(ErrorOrTable); 52 SymtabSHNDX = *ErrorOrTable; 53 break; 54 } 55 case SHT_STRTAB: 56 case SHT_NULL: 57 case SHT_RELA: 58 case SHT_REL: 59 break; 60 default: 61 Chunks[I] = new (Alloc) SectionChunk<ELFT>(this->getObj(), &Sec); 62 break; 63 } 64 ++I; 65 } 66 } 67 68 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() { 69 ErrorOr<StringRef> StringTableOrErr = 70 ELFObj->getStringTableForSymtab(*Symtab); 71 error(StringTableOrErr.getError()); 72 StringRef StringTable = *StringTableOrErr; 73 74 Elf_Sym_Range Syms = ELFObj->symbols(Symtab); 75 uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); 76 uint32_t FirstNonLocal = Symtab->sh_info; 77 if (FirstNonLocal > NumSymbols) 78 error("Invalid sh_info in symbol table"); 79 Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end()); 80 SymbolBodies.reserve(NumSymbols); 81 for (const Elf_Sym &Sym : Syms) 82 SymbolBodies.push_back(createSymbolBody(StringTable, &Sym)); 83 } 84 85 template <class ELFT> 86 SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, 87 const Elf_Sym *Sym) { 88 ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable); 89 error(NameOrErr.getError()); 90 StringRef Name = *NameOrErr; 91 92 uint32_t SecIndex = Sym->st_shndx; 93 if (SecIndex == SHN_XINDEX) 94 SecIndex = ELFObj->getExtendedSymbolTableIndex(Sym, Symtab, SymtabSHNDX); 95 96 if (SecIndex >= Chunks.size() || 97 (SecIndex != 0 && !Chunks[SecIndex])) 98 error("Invalid section index"); 99 100 switch (Sym->getBinding()) { 101 default: 102 error("unexpected binding"); 103 case STB_GLOBAL: 104 if (Sym->isUndefined()) 105 return new (Alloc) Undefined<ELFT>(Name, *Sym); 106 return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, *Chunks[SecIndex]); 107 case STB_WEAK: 108 if (Sym->isUndefined()) 109 return new (Alloc) UndefinedWeak<ELFT>(Name, *Sym); 110 return new (Alloc) DefinedWeak<ELFT>(Name, *Sym, *Chunks[SecIndex]); 111 } 112 } 113 114 namespace lld { 115 namespace elf2 { 116 template class elf2::ObjectFile<llvm::object::ELF32LE>; 117 template class elf2::ObjectFile<llvm::object::ELF32BE>; 118 template class elf2::ObjectFile<llvm::object::ELF64LE>; 119 template class elf2::ObjectFile<llvm::object::ELF64BE>; 120 } 121 } 122