//===- InputFiles.cpp -----------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputFiles.h" #include "Chunks.h" #include "Error.h" #include "Symbols.h" #include "llvm/ADT/STLExtras.h" using namespace llvm::ELF; using namespace llvm::object; using namespace lld; using namespace lld::elf2; template static uint16_t getEMachine(const ELFFileBase &B) { bool IsShared = isa(B); if (IsShared) return cast>(B).getEMachine(); return cast>(B).getEMachine(); } static uint16_t getEMachine(const ELFFileBase &B) { ELFKind K = B.getELFKind(); switch (K) { case ELF32BEKind: return getEMachine(B); case ELF32LEKind: return getEMachine(B); case ELF64BEKind: return getEMachine(B); case ELF64LEKind: return getEMachine(B); } } bool ELFFileBase::isCompatibleWith(const ELFFileBase &Other) const { return getELFKind() == Other.getELFKind() && getEMachine(*this) == getEMachine(Other); } template void ELFData::openELF(MemoryBufferRef MB) { // Parse a memory buffer as a ELF file. std::error_code EC; ELFObj = llvm::make_unique>(MB.getBuffer(), EC); error(EC); } template void elf2::ObjectFile::parse() { this->openELF(MB); // Read section and symbol tables. initializeChunks(); initializeSymbols(); } template void elf2::ObjectFile::initializeChunks() { uint64_t Size = this->ELFObj->getNumSections(); Chunks.resize(Size); unsigned I = 0; for (const Elf_Shdr &Sec : this->ELFObj->sections()) { switch (Sec.sh_type) { case SHT_SYMTAB: Symtab = &Sec; break; case SHT_SYMTAB_SHNDX: { ErrorOr> ErrorOrTable = this->ELFObj->getSHNDXTable(Sec); error(ErrorOrTable); SymtabSHNDX = *ErrorOrTable; break; } case SHT_STRTAB: case SHT_NULL: break; case SHT_RELA: case SHT_REL: { uint32_t RelocatedSectionIndex = Sec.sh_info; if (RelocatedSectionIndex >= Size) error("Invalid relocated section index"); SectionChunk *RelocatedSection = Chunks[RelocatedSectionIndex]; if (!RelocatedSection) error("Unsupported relocation reference"); RelocatedSection->RelocSections.push_back(&Sec); break; } default: Chunks[I] = new (Alloc) SectionChunk(this, &Sec); break; } ++I; } } template void elf2::ObjectFile::initializeSymbols() { ErrorOr StringTableOrErr = this->ELFObj->getStringTableForSymtab(*Symtab); error(StringTableOrErr.getError()); StringRef StringTable = *StringTableOrErr; Elf_Sym_Range Syms = this->ELFObj->symbols(Symtab); uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); uint32_t FirstNonLocal = Symtab->sh_info; if (FirstNonLocal > NumSymbols) error("Invalid sh_info in symbol table"); Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end()); SymbolBodies.reserve(NumSymbols - FirstNonLocal); for (const Elf_Sym &Sym : Syms) SymbolBodies.push_back(createSymbolBody(StringTable, &Sym)); } template SymbolBody *elf2::ObjectFile::createSymbolBody(StringRef StringTable, const Elf_Sym *Sym) { ErrorOr NameOrErr = Sym->getName(StringTable); error(NameOrErr.getError()); StringRef Name = *NameOrErr; uint32_t SecIndex = Sym->st_shndx; switch (SecIndex) { case SHN_ABS: return new (Alloc) DefinedAbsolute(Name, *Sym); case SHN_UNDEF: return new (Alloc) Undefined(Name, *Sym); case SHN_COMMON: return new (Alloc) DefinedCommon(Name, *Sym); case SHN_XINDEX: SecIndex = this->ELFObj->getExtendedSymbolTableIndex(Sym, Symtab, SymtabSHNDX); break; } if (SecIndex >= Chunks.size() || (SecIndex != 0 && !Chunks[SecIndex])) error("Invalid section index"); switch (Sym->getBinding()) { default: error("unexpected binding"); case STB_GLOBAL: case STB_WEAK: return new (Alloc) DefinedRegular(Name, *Sym, *Chunks[SecIndex]); } } template void SharedFile::parse() { this->openELF(MB); } namespace lld { namespace elf2 { template class elf2::ObjectFile; template class elf2::ObjectFile; template class elf2::ObjectFile; template class elf2::ObjectFile; template class elf2::SharedFile; template class elf2::SharedFile; template class elf2::SharedFile; template class elf2::SharedFile; } }