//===- Writer.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Writer.h" #include "Config.h" #include "OutputSections.h" #include "SymbolTable.h" #include "Target.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FileOutputBuffer.h" using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace lld; using namespace lld::elf2; namespace { static uint32_t toPhdrFlags(uint64_t Flags) { uint32_t Ret = PF_R; if (Flags & SHF_WRITE) Ret |= PF_W; if (Flags & SHF_EXECINSTR) Ret |= PF_X; return Ret; } // The writer writes a SymbolTable result to a file. template class Writer { public: typedef typename ELFFile::uintX_t uintX_t; typedef typename ELFFile::Elf_Shdr Elf_Shdr; typedef typename ELFFile::Elf_Ehdr Elf_Ehdr; typedef typename ELFFile::Elf_Phdr Elf_Phdr; typedef typename ELFFile::Elf_Sym Elf_Sym; typedef typename ELFFile::Elf_Sym_Range Elf_Sym_Range; typedef typename ELFFile::Elf_Rela Elf_Rela; Writer(SymbolTable &S) : Symtab(S) {} void run(); private: void copyLocalSymbols(); void createSections(); template void scanRelocs(const InputSection &C, iterator_range *> Rels); void scanRelocs(const InputSection &C); void assignAddresses(); void openFile(StringRef OutputPath); void writeHeader(); void writeSections(); bool needsInterpSection() const { return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty(); } bool isOutputDynamic() const { return !Symtab.getSharedFiles().empty() || Config->Shared; } uintX_t getVAStart() const { return Config->Shared ? 0 : Target->getVAStart(); } std::unique_ptr Buffer; llvm::SpecificBumpPtrAllocator> CAlloc; std::vector *> OutputSections; unsigned getNumSections() const { return OutputSections.size() + 1; } void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff, uintX_t VA, uintX_t Align); void copyPhdr(Elf_Phdr *PH, OutputSectionBase *From); SymbolTable &Symtab; std::vector Phdrs; uintX_t FileSize; uintX_t SectionHeaderOff; }; } // anonymous namespace template void lld::elf2::writeResult(SymbolTable *Symtab) { // Initialize output sections that are handled by Writer specially. // Don't reorder because the order of initialization matters. InterpSection Interp; Out::Interp = &Interp; StringTableSection StrTab(false); Out::StrTab = &StrTab; StringTableSection DynStrTab(true); Out::DynStrTab = &DynStrTab; OutputSection Bss(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); Out::Bss = &Bss; GotSection Got; Out::Got = &Got; PltSection Plt; Out::Plt = &Plt; SymbolTableSection SymTab(*Symtab, *Out::StrTab); Out::SymTab = &SymTab; SymbolTableSection DynSymTab(*Symtab, *Out::DynStrTab); Out::DynSymTab = &DynSymTab; HashTableSection HashTab; Out::HashTab = &HashTab; RelocationSection RelaDyn(Symtab->shouldUseRela()); Out::RelaDyn = &RelaDyn; DynamicSection Dynamic(*Symtab); Out::Dynamic = &Dynamic; Writer(*Symtab).run(); } // The main function of the writer. template void Writer::run() { if (!Config->DiscardAll) copyLocalSymbols(); createSections(); assignAddresses(); openFile(Config->OutputFile); writeHeader(); writeSections(); error(Buffer->commit()); } namespace { template struct SectionKey { typedef typename std::conditional::type uintX_t; StringRef Name; uint32_t Type; uintX_t Flags; }; } namespace llvm { template struct DenseMapInfo> { static SectionKey getEmptyKey() { return SectionKey{DenseMapInfo::getEmptyKey(), 0, 0}; } static SectionKey getTombstoneKey() { return SectionKey{DenseMapInfo::getTombstoneKey(), 0, 0}; } static unsigned getHashValue(const SectionKey &Val) { return hash_combine(Val.Name, Val.Type, Val.Flags); } static bool isEqual(const SectionKey &LHS, const SectionKey &RHS) { return DenseMapInfo::isEqual(LHS.Name, RHS.Name) && LHS.Type == RHS.Type && LHS.Flags == RHS.Flags; } }; } // The reason we have to do this early scan is as follows // * To mmap the output file, we need to know the size // * For that, we need to know how many dynamic relocs we will have. // It might be possible to avoid this by outputting the file with write: // * Write the allocated output sections, computing addresses. // * Apply relocations, recording which ones require a dynamic reloc. // * Write the dynamic relocations. // * Write the rest of the file. template template void Writer::scanRelocs( const InputSection &C, iterator_range *> Rels) { typedef Elf_Rel_Impl RelType; const ObjectFile &File = *C.getFile(); bool IsMips64EL = File.getObj().isMips64EL(); for (const RelType &RI : Rels) { uint32_t SymIndex = RI.getSymbol(IsMips64EL); SymbolBody *Body = File.getSymbolBody(SymIndex); uint32_t Type = RI.getType(IsMips64EL); // Set "used" bit for --as-needed. if (Body && Body->isUndefined() && !Body->isWeak()) if (auto *S = dyn_cast>(Body->repl())) S->File->IsUsed = true; if (Body) Body = Body->repl(); if (Body) { if (Target->relocNeedsPlt(Type, *Body)) { if (Body->isInPlt()) continue; Out::Plt->addEntry(Body); } if (Target->relocNeedsGot(Type, *Body)) { if (Body->isInGot()) continue; Out::Got->addEntry(Body); } } bool CBP = canBePreempted(Body); if (!CBP && (!Config->Shared || Target->isRelRelative(Type))) continue; if (CBP) Body->setUsedInDynamicReloc(); Out::RelaDyn->addReloc({C, RI}); } } template void Writer::scanRelocs(const InputSection &C) { ObjectFile *File = C.getFile(); ELFFile &EObj = File->getObj(); if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC)) return; for (const Elf_Shdr *RelSec : C.RelocSections) { if (RelSec->sh_type == SHT_RELA) scanRelocs(C, EObj.relas(RelSec)); else scanRelocs(C, EObj.rels(RelSec)); } } template static void reportUndefined(const SymbolTable &S, const SymbolBody &Sym) { typedef typename ELFFile::Elf_Sym Elf_Sym; typedef typename ELFFile::Elf_Sym_Range Elf_Sym_Range; if (Config->Shared && !Config->NoUndefined) return; const Elf_Sym &SymE = cast>(Sym).Sym; ELFFileBase *SymFile = nullptr; for (const std::unique_ptr> &File : S.getObjectFiles()) { Elf_Sym_Range Syms = File->getObj().symbols(File->getSymbolTable()); if (&SymE > Syms.begin() && &SymE < Syms.end()) SymFile = File.get(); } std::string Message = "undefined symbol: " + Sym.getName().str(); if (SymFile) Message += " in " + SymFile->getName().str(); if (Config->NoInhibitExec) warning(Message); else error(Message); } // Local symbols are not in the linker's symbol table. This function scans // each object file's symbol table to copy local symbols to the output. template void Writer::copyLocalSymbols() { for (const std::unique_ptr> &F : Symtab.getObjectFiles()) { for (const Elf_Sym &Sym : F->getLocalSymbols()) { ErrorOr SymNameOrErr = Sym.getName(F->getStringTable()); error(SymNameOrErr); StringRef SymName = *SymNameOrErr; if (!shouldKeepInSymtab(*F, SymName, Sym)) continue; Out::SymTab->addSymbol(SymName, true); } } } // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that // we would like to make sure appear is a specific order to maximize their // coverage by a single signed 16-bit offset from the TOC base pointer. // Conversely, the special .tocbss section should be first among all SHT_NOBITS // sections. This will put it next to the loaded special PPC64 sections (and, // thus, within reach of the TOC base pointer). static int getPPC64SectionRank(StringRef SectionName) { return StringSwitch(SectionName) .Case(".tocbss", 0) .Case(".branch_lt", 2) .Case(".toc", 3) .Case(".toc1", 4) .Case(".opd", 5) .Default(1); } // Output section ordering is determined by this function. template static bool compareOutputSections(OutputSectionBase *A, OutputSectionBase *B) { typedef typename ELFFile::uintX_t uintX_t; uintX_t AFlags = A->getFlags(); uintX_t BFlags = B->getFlags(); // Allocatable sections go first to reduce the total PT_LOAD size and // so debug info doesn't change addresses in actual code. bool AIsAlloc = AFlags & SHF_ALLOC; bool BIsAlloc = BFlags & SHF_ALLOC; if (AIsAlloc != BIsAlloc) return AIsAlloc; // We don't have any special requirements for the relative order of // two non allocatable sections. if (!AIsAlloc) return false; // We want the read only sections first so that they go in the PT_LOAD // covering the program headers at the start of the file. bool AIsWritable = AFlags & SHF_WRITE; bool BIsWritable = BFlags & SHF_WRITE; if (AIsWritable != BIsWritable) return BIsWritable; // For a corresponding reason, put non exec sections first (the program // header PT_LOAD is not executable). bool AIsExec = AFlags & SHF_EXECINSTR; bool BIsExec = BFlags & SHF_EXECINSTR; if (AIsExec != BIsExec) return BIsExec; // If we got here we know that both A and B and in the same PT_LOAD. // The last requirement we have is to put nobits section last. The // reason is that the only thing the dynamic linker will see about // them is a p_memsz that is larger than p_filesz. Seeing that it // zeros the end of the PT_LOAD, so that has to correspond to the // nobits sections. if (A->getType() != B->getType()) return A->getType() != SHT_NOBITS && B->getType() == SHT_NOBITS; return getPPC64SectionRank(A->getName()) < getPPC64SectionRank(B->getName()); } // Until this function is called, common symbols do not belong to any section. // This function adds them to end of BSS section. template static void addCommonSymbols(std::vector *> &Syms) { typedef typename ELFFile::uintX_t uintX_t; typedef typename ELFFile::Elf_Sym Elf_Sym; // Sort the common symbols by alignment as an heuristic to pack them better. std::stable_sort( Syms.begin(), Syms.end(), [](const DefinedCommon *A, const DefinedCommon *B) { return A->MaxAlignment > B->MaxAlignment; }); uintX_t Off = Out::Bss->getSize(); for (DefinedCommon *C : Syms) { const Elf_Sym &Sym = C->Sym; uintX_t Align = C->MaxAlignment; Off = RoundUpToAlignment(Off, Align); C->OffsetInBSS = Off; Off += Sym.st_size; } Out::Bss->setSize(Off); } // Create output section objects and add them to OutputSections. template void Writer::createSections() { // .interp needs to be on the first page in the output file. if (needsInterpSection()) OutputSections.push_back(Out::Interp); SmallDenseMap, OutputSection *> Map; OutputSections.push_back(Out::Bss); Map[{Out::Bss->getName(), Out::Bss->getType(), Out::Bss->getFlags()}] = Out::Bss; // Declare linker generated symbols. // This must be done before the relocation scan to make sure we can correctly // decide if a dynamic relocation is needed or not. // FIXME: Make this more declarative. for (StringRef Name : {"__preinit_array_start", "__preinit_array_end", "__init_array_start", "__init_array_end", "__fini_array_start", "__fini_array_end"}) Symtab.addIgnoredSym(Name); // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For // static linking the linker is required to optimize away any references to // __tls_get_addr, so it's not defined anywhere. Create a hidden definition // to avoid the undefined symbol error. if (!isOutputDynamic()) Symtab.addIgnoredSym("__tls_get_addr"); for (const std::unique_ptr> &F : Symtab.getObjectFiles()) { for (InputSection *C : F->getSections()) { if (!C || C == &InputSection::Discarded) continue; const Elf_Shdr *H = C->getSectionHdr(); uintX_t OutFlags = H->sh_flags & ~SHF_GROUP; SectionKey Key{C->getSectionName(), H->sh_type, OutFlags}; OutputSection *&Sec = Map[Key]; if (!Sec) { Sec = new (CAlloc.Allocate()) OutputSection(Key.Name, Key.Type, Key.Flags); OutputSections.push_back(Sec); } Sec->addSection(C); scanRelocs(*C); } } Out::Dynamic->PreInitArraySec = Map.lookup({".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC}); Out::Dynamic->InitArraySec = Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC}); Out::Dynamic->FiniArraySec = Map.lookup({".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC}); auto AddStartEnd = [&](StringRef Start, StringRef End, OutputSection *OS) { if (OS) { Symtab.addSyntheticSym(Start, *OS, 0); Symtab.addSyntheticSym(End, *OS, OS->getSize()); } }; AddStartEnd("__preinit_array_start", "__preinit_array_end", Out::Dynamic->PreInitArraySec); AddStartEnd("__init_array_start", "__init_array_end", Out::Dynamic->InitArraySec); AddStartEnd("__fini_array_start", "__fini_array_end", Out::Dynamic->FiniArraySec); // FIXME: Try to avoid the extra walk over all global symbols. std::vector *> CommonSymbols; for (auto &P : Symtab.getSymbols()) { StringRef Name = P.first; SymbolBody *Body = P.second->Body; if (auto *U = dyn_cast>(Body)) { if (!U->isWeak() && !U->canKeepUndefined()) reportUndefined(Symtab, *Body); } if (auto *C = dyn_cast>(Body)) CommonSymbols.push_back(C); if (!includeInSymtab(*Body)) continue; Out::SymTab->addSymbol(Name); if (isOutputDynamic() && includeInDynamicSymtab(*Body)) Out::HashTab->addSymbol(Body); } addCommonSymbols(CommonSymbols); OutputSections.push_back(Out::SymTab); if (isOutputDynamic()) { OutputSections.push_back(Out::DynSymTab); OutputSections.push_back(Out::HashTab); OutputSections.push_back(Out::Dynamic); OutputSections.push_back(Out::DynStrTab); if (Out::RelaDyn->hasRelocs()) OutputSections.push_back(Out::RelaDyn); } if (!Out::Got->empty()) OutputSections.push_back(Out::Got); if (!Out::Plt->empty()) OutputSections.push_back(Out::Plt); std::stable_sort(OutputSections.begin(), OutputSections.end(), compareOutputSections); // Always put StrTabSec last so that no section names are added to it after // it's finalized. OutputSections.push_back(Out::StrTab); for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) OutputSections[I]->setSectionIndex(I + 1); // Fill the DynStrTab early. Out::Dynamic->finalize(); // Fix each section's header (e.g. sh_size, sh_link, etc.) for (OutputSectionBase *Sec : OutputSections) { Out::StrTab->add(Sec->getName()); Sec->finalize(); } // If we have a .opd section (used under PPC64 for function descriptors), // store a pointer to it here so that we can use it later when processing // relocations. Out::Opd = Map.lookup({".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC}); } template static bool needsPhdr(OutputSectionBase *Sec) { return Sec->getFlags() & SHF_ALLOC; } // Visits all sections to assign incremental, non-overlapping RVAs and // file offsets. template void Writer::assignAddresses() { assert(!OutputSections.empty() && "No output sections to layout!"); uintX_t VA = getVAStart() + sizeof(Elf_Ehdr); uintX_t FileOff = sizeof(Elf_Ehdr); // Reserve space for Phdrs. int NumPhdrs = 2; // 2 for PhdrPhdr and FileHeaderPhdr if (needsInterpSection()) ++NumPhdrs; if (isOutputDynamic()) ++NumPhdrs; uintX_t Last = PF_R; for (OutputSectionBase *Sec : OutputSections) { if (!Sec->getSize() || !needsPhdr(Sec)) continue; uintX_t Flags = toPhdrFlags(Sec->getFlags()); if (Last != Flags) { Last = Flags; ++NumPhdrs; } } // Reserve space needed for the program header so that the array // will never be resized. Phdrs.reserve(NumPhdrs); // The first Phdr entry is PT_PHDR which describes the program header itself. Phdrs.emplace_back(); Elf_Phdr *PhdrPhdr = &Phdrs.back(); setPhdr(PhdrPhdr, PT_PHDR, PF_R, FileOff, VA, /*Align=*/8); FileOff += sizeof(Elf_Phdr) * NumPhdrs; VA += sizeof(Elf_Phdr) * NumPhdrs; Elf_Phdr *Interp = nullptr; if (needsInterpSection()) { Phdrs.emplace_back(); Interp = &Phdrs.back(); } // Create a Phdr for the file header. Phdrs.emplace_back(); Elf_Phdr *FileHeader = &Phdrs.back(); setPhdr(FileHeader, PT_LOAD, PF_R, 0, getVAStart(), Target->getPageSize()); SmallPtrSet Closed; for (OutputSectionBase *Sec : OutputSections) { if (Sec->getSize()) { uintX_t Flags = toPhdrFlags(Sec->getFlags()); Elf_Phdr *Last = &Phdrs.back(); if (Last->p_flags != Flags || !needsPhdr(Sec)) { // Flags changed. End current Phdr and potentially create a new one. if (Closed.insert(Last).second) { Last->p_filesz = FileOff - Last->p_offset; Last->p_memsz = VA - Last->p_vaddr; } if (needsPhdr(Sec)) { VA = RoundUpToAlignment(VA, Target->getPageSize()); FileOff = RoundUpToAlignment(FileOff, Target->getPageSize()); Phdrs.emplace_back(); Elf_Phdr *PH = &Phdrs.back(); setPhdr(PH, PT_LOAD, Flags, FileOff, VA, Target->getPageSize()); } } } uintX_t Align = Sec->getAlign(); uintX_t Size = Sec->getSize(); if (Sec->getFlags() & SHF_ALLOC) { VA = RoundUpToAlignment(VA, Align); Sec->setVA(VA); VA += Size; } FileOff = RoundUpToAlignment(FileOff, Align); Sec->setFileOffset(FileOff); if (Sec->getType() != SHT_NOBITS) FileOff += Size; } if (Interp) { Interp->p_type = PT_INTERP; copyPhdr(Interp, Out::Interp); } if (isOutputDynamic()) { Phdrs.emplace_back(); Elf_Phdr *PH = &Phdrs.back(); PH->p_type = PT_DYNAMIC; copyPhdr(PH, Out::Dynamic); } // Fix up the first entry's size. PhdrPhdr->p_filesz = sizeof(Elf_Phdr) * Phdrs.size(); PhdrPhdr->p_memsz = sizeof(Elf_Phdr) * Phdrs.size(); // If nothing was merged into the file header PT_LOAD, set the size correctly. if (FileHeader->p_filesz == Target->getPageSize()) { uint64_t Size = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * Phdrs.size(); FileHeader->p_filesz = Size; FileHeader->p_memsz = Size; } // Add space for section headers. FileOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4); SectionHeaderOff = FileOff; FileOff += getNumSections() * sizeof(Elf_Shdr); FileSize = FileOff; } template void Writer::writeHeader() { uint8_t *Buf = Buffer->getBufferStart(); auto *EHdr = reinterpret_cast(Buf); EHdr->e_ident[EI_MAG0] = 0x7F; EHdr->e_ident[EI_MAG1] = 0x45; EHdr->e_ident[EI_MAG2] = 0x4C; EHdr->e_ident[EI_MAG3] = 0x46; EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; EHdr->e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little ? ELFDATA2LSB : ELFDATA2MSB; EHdr->e_ident[EI_VERSION] = EV_CURRENT; auto &FirstObj = cast>(*Config->FirstElf); EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI(); // FIXME: Generalize the segment construction similar to how we create // output sections. EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC; EHdr->e_machine = FirstObj.getEMachine(); EHdr->e_version = EV_CURRENT; if (Config->EntrySym) if (auto *E = dyn_cast>(Config->EntrySym->repl())) EHdr->e_entry = getSymVA(*E); EHdr->e_phoff = sizeof(Elf_Ehdr); EHdr->e_shoff = SectionHeaderOff; EHdr->e_ehsize = sizeof(Elf_Ehdr); EHdr->e_phentsize = sizeof(Elf_Phdr); EHdr->e_phnum = Phdrs.size(); EHdr->e_shentsize = sizeof(Elf_Shdr); EHdr->e_shnum = getNumSections(); EHdr->e_shstrndx = Out::StrTab->getSectionIndex(); memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0])); auto SHdrs = reinterpret_cast(Buf + EHdr->e_shoff); // First entry is null. ++SHdrs; for (OutputSectionBase *Sec : OutputSections) { Sec->setNameOffset(Out::StrTab->getFileOff(Sec->getName())); Sec->template writeHeaderTo(SHdrs++); } } template void Writer::openFile(StringRef Path) { ErrorOr> BufferOrErr = FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable); error(BufferOrErr, Twine("failed to open ") + Path); Buffer = std::move(*BufferOrErr); } // Write section contents to a mmap'ed file. template void Writer::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); // PPC64 needs to process relocations in the .opd section before processing // relocations in code-containing sections. if (OutputSectionBase *Sec = Out::Opd) { Out::OpdBuf = Buf + Sec->getFileOff(); Sec->writeTo(Buf + Sec->getFileOff()); } for (OutputSectionBase *Sec : OutputSections) if (Sec != Out::Opd) Sec->writeTo(Buf + Sec->getFileOff()); } template void Writer::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff, uintX_t VA, uintX_t Align) { PH->p_type = Type; PH->p_flags = Flags; PH->p_offset = FileOff; PH->p_vaddr = VA; PH->p_paddr = VA; PH->p_align = Align; } template void Writer::copyPhdr(Elf_Phdr *PH, OutputSectionBase *From) { PH->p_flags = toPhdrFlags(From->getFlags()); PH->p_offset = From->getFileOff(); PH->p_vaddr = From->getVA(); PH->p_paddr = From->getVA(); PH->p_filesz = From->getSize(); PH->p_memsz = From->getSize(); PH->p_align = From->getAlign(); } template void lld::elf2::writeResult(SymbolTable *Symtab); template void lld::elf2::writeResult(SymbolTable *Symtab); template void lld::elf2::writeResult(SymbolTable *Symtab); template void lld::elf2::writeResult(SymbolTable *Symtab);