//===- 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.resize(Size); unsigned I = 0; for (const Elf_Shdr &Sec : ELFObj->sections()) { switch (Sec.sh_type) { case SHT_SYMTAB: Symtab = &Sec; break; case SHT_STRTAB: case SHT_NULL: case SHT_RELA: case SHT_REL: break; default: Chunks[I] = new (Alloc) SectionChunk(this->getObj(), &Sec); break; } ++I; } } template void elf2::ObjectFile::initializeSymbols() { ErrorOr StringTableOrErr = ELFObj->getStringTableForSymtab(*Symtab); error(StringTableOrErr.getError()); StringRef StringTable = *StringTableOrErr; Elf_Sym_Range Syms = 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); 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; uint16_t SecIndex = Sym->st_shndx; switch (Sym->getBinding()) { default: error("unexpected binding"); case STB_GLOBAL: if (Sym->isUndefined()) return new (Alloc) Undefined(Name, *Sym); return new (Alloc) DefinedRegular(Name, *Sym, *Chunks[SecIndex]); case STB_WEAK: if (Sym->isUndefined()) return new (Alloc) UndefinedWeak(Name, *Sym); return new (Alloc) DefinedWeak(Name, *Sym, *Chunks[SecIndex]); } } namespace lld { namespace elf2 { template class elf2::ObjectFile; template class elf2::ObjectFile; template class elf2::ObjectFile; template class elf2::ObjectFile; } }