//===- 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 lld; using namespace lld::elf2; template bool ObjectFile::isCompatibleWith(const ObjectFileBase &Other) const { if (kind() != Other.kind()) return false; return getObj()->getHeader()->e_machine == cast>(Other).getObj()->getHeader()->e_machine; } template void elf2::ObjectFile::parse() { // Parse a memory buffer as a ELF file. std::error_code EC; ELFObj = llvm::make_unique>(MB.getBuffer(), EC); error(EC); // Read section and symbol tables. initializeChunks(); initializeSymbols(); } template void elf2::ObjectFile::initializeChunks() { uint64_t Size = ELFObj->getNumSections(); Chunks.reserve(Size); for (const Elf_Shdr &Sec : ELFObj->sections()) { if (Sec.sh_type == SHT_SYMTAB) { Symtab = &Sec; continue; } if (Sec.sh_flags & SHF_ALLOC) { auto *C = new (Alloc) SectionChunk(this->getObj(), &Sec); Chunks.push_back(C); } } } template void elf2::ObjectFile::initializeSymbols() { ErrorOr StringTableOrErr = ELFObj->getStringTableForSymtab(*Symtab); error(StringTableOrErr.getError()); StringRef StringTable = *StringTableOrErr; Elf_Sym_Range Syms = ELFObj->symbols(Symtab); auto 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); 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; switch (Sym->getBinding()) { default: error("unexpected binding"); case STB_GLOBAL: if (Sym->isUndefined()) return new (Alloc) Undefined(Name); return new (Alloc) DefinedRegular(Name); case STB_WEAK: if (Sym->isUndefined()) return new (Alloc) UndefinedWeak(Name); return new (Alloc) DefinedWeak(Name); } } namespace lld { namespace elf2 { template class elf2::ObjectFile; template class elf2::ObjectFile; template class elf2::ObjectFile; template class elf2::ObjectFile; } }