diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:48:50 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:48:50 +0000 |
commit | 1c98619801a5705c688e683be3ef9d70169a0686 (patch) | |
tree | 8422105cd1a94c368315f2db16b9ac746cf7c000 /ELF/Writer.cpp | |
parent | f4f3ce4613680903220815690ad79fc7ba0a2e26 (diff) | |
download | src-1c98619801a5705c688e683be3ef9d70169a0686.tar.gz src-1c98619801a5705c688e683be3ef9d70169a0686.zip |
Vendor import of lld release_39 branch r276489:vendor/lld/lld-release_39-r276489
Notes
Notes:
svn path=/vendor/lld/dist/; revision=303239
svn path=/vendor/lld/lld-release_39-r276489/; revision=303240; tag=vendor/lld/lld-release_39-r276489
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r-- | ELF/Writer.cpp | 1564 |
1 files changed, 769 insertions, 795 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index fbecfc601ac1..387bec3d8fb2 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -9,362 +9,353 @@ #include "Writer.h" #include "Config.h" +#include "LinkerScript.h" #include "OutputSections.h" +#include "Relocations.h" +#include "Strings.h" #include "SymbolTable.h" #include "Target.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FileOutputBuffer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace lld; -using namespace lld::elf2; +using namespace lld::elf; namespace { // The writer writes a SymbolTable result to a file. template <class ELFT> class Writer { public: - typedef typename ELFFile<ELFT>::uintX_t uintX_t; - typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; - typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr; - typedef typename ELFFile<ELFT>::Elf_Phdr Elf_Phdr; - typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; - typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; - typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela; + typedef typename ELFT::uint uintX_t; + typedef typename ELFT::Shdr Elf_Shdr; + typedef typename ELFT::Ehdr Elf_Ehdr; + typedef typename ELFT::Phdr Elf_Phdr; + typedef typename ELFT::Sym Elf_Sym; + typedef typename ELFT::SymRange Elf_Sym_Range; + typedef typename ELFT::Rela Elf_Rela; Writer(SymbolTable<ELFT> &S) : Symtab(S) {} void run(); private: + // This describes a program header entry. + // Each contains type, access flags and range of output sections that will be + // placed in it. + struct Phdr { + Phdr(unsigned Type, unsigned Flags) { + H.p_type = Type; + H.p_flags = Flags; + } + Elf_Phdr H = {}; + OutputSectionBase<ELFT> *First = nullptr; + OutputSectionBase<ELFT> *Last = nullptr; + }; + void copyLocalSymbols(); void addReservedSymbols(); void createSections(); void addPredefinedSections(); + bool needsGot(); - template <bool isRela> - void scanRelocs(InputSectionBase<ELFT> &C, - iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels); - - void scanRelocs(InputSection<ELFT> &C); - void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec); - void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, uintX_t VA); + void createPhdrs(); void assignAddresses(); - void buildSectionMap(); + void assignFileOffsets(); + void setPhdrs(); + void fixHeaders(); + void fixSectionAlignments(); void fixAbsoluteSymbols(); - void openFile(StringRef OutputPath); + void openFile(); void writeHeader(); void writeSections(); - bool isDiscarded(InputSectionBase<ELFT> *IS) const; - StringRef getOutputSectionName(StringRef S) const; + void writeBuildId(); bool needsInterpSection() const { return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty(); } bool isOutputDynamic() const { - return !Symtab.getSharedFiles().empty() || Config->Shared; + return !Symtab.getSharedFiles().empty() || Config->Pic; } - int getPhdrsNum() const; - OutputSection<ELFT> *getBss(); void addCommonSymbols(std::vector<DefinedCommon *> &Syms); - void addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms); - std::unique_ptr<llvm::FileOutputBuffer> Buffer; + std::unique_ptr<FileOutputBuffer> Buffer; BumpPtrAllocator Alloc; std::vector<OutputSectionBase<ELFT> *> OutputSections; std::vector<std::unique_ptr<OutputSectionBase<ELFT>>> OwningSections; - unsigned getNumSections() const { return OutputSections.size() + 1; } void addRelIpltSymbols(); void addStartEndSymbols(); void addStartStopSymbols(OutputSectionBase<ELFT> *Sec); - void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff, - uintX_t VA, uintX_t Size, uintX_t Align); - void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From); - bool HasRelro = false; SymbolTable<ELFT> &Symtab; - std::vector<Elf_Phdr> Phdrs; + std::vector<Phdr> Phdrs; uintX_t FileSize; uintX_t SectionHeaderOff; - - llvm::StringMap<llvm::StringRef> InputToOutputSection; }; } // anonymous namespace -template <class ELFT> static bool shouldUseRela() { return ELFT::Is64Bits; } +template <class ELFT> +StringRef elf::getOutputSectionName(InputSectionBase<ELFT> *S) { + StringRef Dest = Script<ELFT>::X->getOutputSection(S); + if (!Dest.empty()) + return Dest; + + StringRef Name = S->getSectionName(); + for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.", + ".init_array.", ".fini_array.", ".ctors.", ".dtors.", + ".tbss.", ".gcc_except_table.", ".tdata."}) + if (Name.startswith(V)) + return V.drop_back(); + return Name; +} -template <class ELFT> void elf2::writeResult(SymbolTable<ELFT> *Symtab) { - // Initialize output sections that are handled by Writer specially. - // Don't reorder because the order of initialization matters. - InterpSection<ELFT> Interp; - Out<ELFT>::Interp = &Interp; - StringTableSection<ELFT> ShStrTab(".shstrtab", false); - Out<ELFT>::ShStrTab = &ShStrTab; - StringTableSection<ELFT> StrTab(".strtab", false); - if (!Config->StripAll) - Out<ELFT>::StrTab = &StrTab; - StringTableSection<ELFT> DynStrTab(".dynstr", true); - Out<ELFT>::DynStrTab = &DynStrTab; +template <class ELFT> +void elf::reportDiscarded(InputSectionBase<ELFT> *IS, + const std::unique_ptr<elf::ObjectFile<ELFT>> &File) { + if (!Config->PrintGcSections || !IS || IS->Live) + return; + errs() << "removing unused section from '" << IS->getSectionName() + << "' in file '" << File->getName() << "'\n"; +} + +template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) { + typedef typename ELFT::uint uintX_t; + typedef typename ELFT::Ehdr Elf_Ehdr; + + // Create singleton output sections. + OutputSection<ELFT> Bss(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); + DynamicSection<ELFT> Dynamic; + EhOutputSection<ELFT> EhFrame; GotSection<ELFT> Got; - Out<ELFT>::Got = &Got; - GotPltSection<ELFT> GotPlt; - if (Target->supportsLazyRelocations()) - Out<ELFT>::GotPlt = &GotPlt; + InterpSection<ELFT> Interp; PltSection<ELFT> Plt; - Out<ELFT>::Plt = &Plt; - std::unique_ptr<SymbolTableSection<ELFT>> SymTab; + RelocationSection<ELFT> RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn", + Config->ZCombreloc); + StringTableSection<ELFT> DynStrTab(".dynstr", true); + StringTableSection<ELFT> ShStrTab(".shstrtab", false); + SymbolTableSection<ELFT> DynSymTab(DynStrTab); + VersionTableSection<ELFT> VerSym; + VersionNeedSection<ELFT> VerNeed; + + OutputSectionBase<ELFT> ElfHeader("", 0, SHF_ALLOC); + ElfHeader.setSize(sizeof(Elf_Ehdr)); + OutputSectionBase<ELFT> ProgramHeaders("", 0, SHF_ALLOC); + ProgramHeaders.updateAlignment(sizeof(uintX_t)); + + // Instantiate optional output sections if they are needed. + std::unique_ptr<BuildIdSection<ELFT>> BuildId; + std::unique_ptr<EhFrameHeader<ELFT>> EhFrameHdr; + std::unique_ptr<GnuHashTableSection<ELFT>> GnuHashTab; + std::unique_ptr<GotPltSection<ELFT>> GotPlt; + std::unique_ptr<HashTableSection<ELFT>> HashTab; + std::unique_ptr<RelocationSection<ELFT>> RelaPlt; + std::unique_ptr<StringTableSection<ELFT>> StrTab; + std::unique_ptr<SymbolTableSection<ELFT>> SymTabSec; + std::unique_ptr<OutputSection<ELFT>> MipsRldMap; + std::unique_ptr<VersionDefinitionSection<ELFT>> VerDef; + + if (Config->BuildId == BuildIdKind::Fnv1) + BuildId.reset(new BuildIdFnv1<ELFT>); + else if (Config->BuildId == BuildIdKind::Md5) + BuildId.reset(new BuildIdMd5<ELFT>); + else if (Config->BuildId == BuildIdKind::Sha1) + BuildId.reset(new BuildIdSha1<ELFT>); + else if (Config->BuildId == BuildIdKind::Hexstring) + BuildId.reset(new BuildIdHexstring<ELFT>); + + if (Config->EhFrameHdr) + EhFrameHdr.reset(new EhFrameHeader<ELFT>); + + if (Config->GnuHash) + GnuHashTab.reset(new GnuHashTableSection<ELFT>); + if (Config->SysvHash) + HashTab.reset(new HashTableSection<ELFT>); + StringRef S = Config->Rela ? ".rela.plt" : ".rel.plt"; + GotPlt.reset(new GotPltSection<ELFT>); + RelaPlt.reset(new RelocationSection<ELFT>(S, false /*Sort*/)); if (!Config->StripAll) { - SymTab.reset(new SymbolTableSection<ELFT>(*Symtab, *Out<ELFT>::StrTab)); - Out<ELFT>::SymTab = SymTab.get(); + StrTab.reset(new StringTableSection<ELFT>(".strtab", false)); + SymTabSec.reset(new SymbolTableSection<ELFT>(*StrTab)); } - SymbolTableSection<ELFT> DynSymTab(*Symtab, *Out<ELFT>::DynStrTab); + if (Config->EMachine == EM_MIPS && !Config->Shared) { + // This is a MIPS specific section to hold a space within the data segment + // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry. + // See "Dynamic section" in Chapter 5 in the following document: + // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + MipsRldMap.reset(new OutputSection<ELFT>(".rld_map", SHT_PROGBITS, + SHF_ALLOC | SHF_WRITE)); + MipsRldMap->setSize(sizeof(uintX_t)); + MipsRldMap->updateAlignment(sizeof(uintX_t)); + } + if (!Config->VersionDefinitions.empty()) + VerDef.reset(new VersionDefinitionSection<ELFT>()); + + Out<ELFT>::Bss = &Bss; + Out<ELFT>::BuildId = BuildId.get(); + Out<ELFT>::DynStrTab = &DynStrTab; Out<ELFT>::DynSymTab = &DynSymTab; - HashTableSection<ELFT> HashTab; - if (Config->SysvHash) - Out<ELFT>::HashTab = &HashTab; - GnuHashTableSection<ELFT> GnuHashTab; - if (Config->GnuHash) - Out<ELFT>::GnuHashTab = &GnuHashTab; - bool IsRela = shouldUseRela<ELFT>(); - RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela); - Out<ELFT>::RelaDyn = &RelaDyn; - RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela); - if (Target->supportsLazyRelocations()) - Out<ELFT>::RelaPlt = &RelaPlt; - DynamicSection<ELFT> Dynamic(*Symtab); Out<ELFT>::Dynamic = &Dynamic; + Out<ELFT>::EhFrame = &EhFrame; + Out<ELFT>::EhFrameHdr = EhFrameHdr.get(); + Out<ELFT>::GnuHashTab = GnuHashTab.get(); + Out<ELFT>::Got = &Got; + Out<ELFT>::GotPlt = GotPlt.get(); + Out<ELFT>::HashTab = HashTab.get(); + Out<ELFT>::Interp = &Interp; + Out<ELFT>::Plt = &Plt; + Out<ELFT>::RelaDyn = &RelaDyn; + Out<ELFT>::RelaPlt = RelaPlt.get(); + Out<ELFT>::ShStrTab = &ShStrTab; + Out<ELFT>::StrTab = StrTab.get(); + Out<ELFT>::SymTab = SymTabSec.get(); + Out<ELFT>::VerDef = VerDef.get(); + Out<ELFT>::VerSym = &VerSym; + Out<ELFT>::VerNeed = &VerNeed; + Out<ELFT>::MipsRldMap = MipsRldMap.get(); + Out<ELFT>::Opd = nullptr; + Out<ELFT>::OpdBuf = nullptr; + Out<ELFT>::TlsPhdr = nullptr; + Out<ELFT>::ElfHeader = &ElfHeader; + Out<ELFT>::ProgramHeaders = &ProgramHeaders; Writer<ELFT>(*Symtab).run(); } // The main function of the writer. template <class ELFT> void Writer<ELFT>::run() { - buildSectionMap(); if (!Config->DiscardAll) copyLocalSymbols(); addReservedSymbols(); createSections(); - assignAddresses(); - fixAbsoluteSymbols(); - openFile(Config->OutputFile); - writeHeader(); - writeSections(); - error(Buffer->commit()); -} + if (HasError) + return; -namespace { -template <bool Is64Bits> struct SectionKey { - typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t; - StringRef Name; - uint32_t Type; - uintX_t Flags; - uintX_t EntSize; -}; -} -namespace llvm { -template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> { - static SectionKey<Is64Bits> getEmptyKey() { - return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0, - 0}; - } - static SectionKey<Is64Bits> getTombstoneKey() { - return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0, - 0, 0}; - } - static unsigned getHashValue(const SectionKey<Is64Bits> &Val) { - return hash_combine(Val.Name, Val.Type, Val.Flags, Val.EntSize); - } - static bool isEqual(const SectionKey<Is64Bits> &LHS, - const SectionKey<Is64Bits> &RHS) { - return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) && - LHS.Type == RHS.Type && LHS.Flags == RHS.Flags && - LHS.EntSize == RHS.EntSize; + if (Config->Relocatable) { + assignFileOffsets(); + } else { + createPhdrs(); + fixHeaders(); + if (ScriptConfig->DoLayout) { + Script<ELFT>::X->assignAddresses(OutputSections); + } else { + fixSectionAlignments(); + assignAddresses(); + } + assignFileOffsets(); + setPhdrs(); + fixAbsoluteSymbols(); } -}; + + openFile(); + if (HasError) + return; + writeHeader(); + writeSections(); + writeBuildId(); + if (HasError) + return; + if (auto EC = Buffer->commit()) + error(EC, "failed to write to the output file"); } -// 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 <class ELFT> -template <bool isRela> -void Writer<ELFT>::scanRelocs( - InputSectionBase<ELFT> &C, - iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) { - typedef Elf_Rel_Impl<ELFT, isRela> RelType; - const ObjectFile<ELFT> &File = *C.getFile(); - for (const RelType &RI : Rels) { - uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); - SymbolBody *Body = File.getSymbolBody(SymIndex); - uint32_t Type = RI.getType(Config->Mips64EL); - - if (Target->isGotRelative(Type)) - HasGotOffRel = true; - - if (Target->isTlsLocalDynamicReloc(Type)) { - if (Target->isTlsOptimized(Type, nullptr)) - continue; - if (Out<ELFT>::Got->addCurrentModuleTlsIndex()) - Out<ELFT>::RelaDyn->addReloc({&C, &RI}); - continue; - } - - // Set "used" bit for --as-needed. - if (Body && Body->isUndefined() && !Body->isWeak()) - if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl())) - S->File->IsUsed = true; - - if (Body) - Body = Body->repl(); - - if (Body && Body->isTls() && Target->isTlsGlobalDynamicReloc(Type)) { - bool Opt = Target->isTlsOptimized(Type, Body); - if (!Opt && Out<ELFT>::Got->addDynTlsEntry(Body)) { - Out<ELFT>::RelaDyn->addReloc({&C, &RI}); - Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr}); - Body->setUsedInDynamicReloc(); - continue; - } - if (!canBePreempted(Body, true)) - continue; - } - - if (Body && Body->isTls() && !Target->isTlsDynReloc(Type, *Body)) - continue; +static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) { + if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore) + return; - if (Target->relocNeedsDynRelative(Type)) { - RelType *Rel = new (Alloc) RelType; - Rel->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL); - Rel->r_offset = RI.r_offset; - Out<ELFT>::RelaDyn->addReloc({&C, Rel}); - } + if (Config->Shared && Sym->symbol()->Visibility == STV_DEFAULT && + Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef) + return; - bool NeedsGot = false; - bool NeedsPlt = false; - if (Body) { - if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) { - if (E->NeedsCopy) - continue; - if (Target->needsCopyRel(Type, *Body)) - E->NeedsCopy = true; - } - NeedsPlt = Target->relocNeedsPlt(Type, *Body); - if (NeedsPlt) { - if (Body->isInPlt()) - continue; - Out<ELFT>::Plt->addEntry(Body); - } - NeedsGot = Target->relocNeedsGot(Type, *Body); - if (NeedsGot) { - if (NeedsPlt && Target->supportsLazyRelocations()) { - Out<ELFT>::GotPlt->addEntry(Body); - } else { - if (Body->isInGot()) - continue; - Out<ELFT>::Got->addEntry(Body); - } - } - } + std::string Msg = "undefined symbol: " + Sym->getName().str(); + if (Sym->File) + Msg += " in " + getFilename(Sym->File); + if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn) + warning(Msg); + else + error(Msg); +} - // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references - // to the symbol go through the PLT. This is true even for a local - // symbol, although local symbols normally do not require PLT entries. - if (Body && isGnuIFunc<ELFT>(*Body)) { - Body->setUsedInDynamicReloc(); - Out<ELFT>::RelaPlt->addReloc({&C, &RI}); - continue; - } +template <class ELFT> +static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName, + const SymbolBody &B) { + if (B.isFile()) + return false; - if (Config->EMachine == EM_MIPS) { - if (NeedsGot) { - // MIPS ABI has special rules to process GOT entries - // and doesn't require relocation entries for them. - // See "Global Offset Table" in Chapter 5 in the following document - // for detailed description: - // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - Body->setUsedInDynamicReloc(); - continue; - } - if (Body == Config->MipsGpDisp) - // MIPS _gp_disp designates offset between start of function and gp - // pointer into GOT therefore any relocations against it do not require - // dynamic relocation. - continue; - } + // We keep sections in symtab for relocatable output. + if (B.isSection()) + return Config->Relocatable; - // Here we are creating a relocation for the dynamic linker based on - // a relocation from an object file, but some relocations need no - // load-time fixup. Skip such relocation. - bool CBP = canBePreempted(Body, NeedsGot); - bool NoDynrel = Target->isRelRelative(Type) || Target->isSizeReloc(Type); - if (!CBP && (NoDynrel || !Config->Shared)) - continue; + // If sym references a section in a discarded group, don't keep it. + if (Sec == &InputSection<ELFT>::Discarded) + return false; - if (CBP) - Body->setUsedInDynamicReloc(); - if (NeedsPlt && Target->supportsLazyRelocations()) - Out<ELFT>::RelaPlt->addReloc({&C, &RI}); - else - Out<ELFT>::RelaDyn->addReloc({&C, &RI}); - } -} + if (Config->DiscardNone) + return true; -template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) { - if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC)) - return; + // In ELF assembly .L symbols are normally discarded by the assembler. + // If the assembler fails to do so, the linker discards them if + // * --discard-locals is used. + // * The symbol is in a SHF_MERGE section, which is normally the reason for + // the assembler keeping the .L symbol. + if (!SymName.startswith(".L") && !SymName.empty()) + return true; - for (const Elf_Shdr *RelSec : C.RelocSections) - scanRelocs(C, *RelSec); -} + if (Config->DiscardLocals) + return false; -template <class ELFT> -void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S, - const Elf_Shdr &RelSec) { - ELFFile<ELFT> &EObj = S.getFile()->getObj(); - if (RelSec.sh_type == SHT_RELA) - scanRelocs(S, EObj.relas(&RelSec)); - else - scanRelocs(S, EObj.rels(&RelSec)); + return !(Sec->getSectionHdr()->sh_flags & SHF_MERGE); } -template <class ELFT> -static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) { - if (Config->Shared && !Config->NoUndefined) - return; +template <class ELFT> static bool includeInSymtab(const SymbolBody &B) { + if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj) + return false; - std::string Msg = "undefined symbol: " + Sym->getName().str(); - if (ELFFileBase<ELFT> *File = Symtab.findFile(Sym)) - Msg += " in " + File->getName().str(); - if (Config->NoInhibitExec) - warning(Msg); - else - error(Msg); + if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) { + // Always include absolute symbols. + if (!D->Section) + return true; + // Exclude symbols pointing to garbage-collected sections. + if (!D->Section->Live) + return false; + if (auto *S = dyn_cast<MergeInputSection<ELFT>>(D->Section)) + if (!S->getSectionPiece(D->Value)->Live) + return false; + } + return true; } // 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 <class ELFT> void Writer<ELFT>::copyLocalSymbols() { - for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) { - for (const Elf_Sym &Sym : F->getLocalSymbols()) { - ErrorOr<StringRef> SymNameOrErr = Sym.getName(F->getStringTable()); - error(SymNameOrErr); - StringRef SymName = *SymNameOrErr; - if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym)) + if (!Out<ELFT>::SymTab) + return; + for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F : + Symtab.getObjectFiles()) { + const char *StrTab = F->getStringTable().data(); + for (SymbolBody *B : F->getLocalSymbols()) { + auto *DR = dyn_cast<DefinedRegular<ELFT>>(B); + // No reason to keep local undefined symbol in symtab. + if (!DR) continue; - if (Out<ELFT>::SymTab) - Out<ELFT>::SymTab->addLocalSymbol(SymName); + if (!includeInSymtab<ELFT>(*B)) + continue; + StringRef SymName(StrTab + B->getNameOffset()); + InputSectionBase<ELFT> *Sec = DR->Section; + if (!shouldKeepInSymtab<ELFT>(Sec, SymName, *B)) + continue; + ++Out<ELFT>::SymTab->NumLocals; + if (Config->Relocatable) + B->DynsymIndex = Out<ELFT>::SymTab->NumLocals; + F->KeptLocalSyms.push_back( + std::make_pair(DR, Out<ELFT>::SymTab->StrTabSec.addString(SymName))); } } } @@ -377,16 +368,18 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { // thus, within reach of the TOC base pointer). static int getPPC64SectionRank(StringRef SectionName) { return StringSwitch<int>(SectionName) - .Case(".tocbss", 0) - .Case(".branch_lt", 2) - .Case(".toc", 3) - .Case(".toc1", 4) - .Case(".opd", 5) - .Default(1); + .Case(".tocbss", 0) + .Case(".branch_lt", 2) + .Case(".toc", 3) + .Case(".toc1", 4) + .Case(".opd", 5) + .Default(1); } template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) { - typename OutputSectionBase<ELFT>::uintX_t Flags = Sec->getFlags(); + if (!Config->ZRelro) + return false; + typename ELFT::uint Flags = Sec->getFlags(); if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE)) return false; if (Flags & SHF_TLS) @@ -406,9 +399,13 @@ template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) { // Output section ordering is determined by this function. template <class ELFT> -static bool compareOutputSections(OutputSectionBase<ELFT> *A, - OutputSectionBase<ELFT> *B) { - typedef typename ELFFile<ELFT>::uintX_t uintX_t; +static bool compareSections(OutputSectionBase<ELFT> *A, + OutputSectionBase<ELFT> *B) { + typedef typename ELFT::uint uintX_t; + + int Comp = Script<ELFT>::X->compareSections(A->getName(), B->getName()); + if (Comp != 0) + return Comp < 0; uintX_t AFlags = A->getFlags(); uintX_t BFlags = B->getFlags(); @@ -475,16 +472,6 @@ static bool compareOutputSections(OutputSectionBase<ELFT> *A, return false; } -template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBss() { - if (!Out<ELFT>::Bss) { - Out<ELFT>::Bss = - new OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); - OwningSections.emplace_back(Out<ELFT>::Bss); - OutputSections.push_back(Out<ELFT>::Bss); - } - return Out<ELFT>::Bss; -} - // Until this function is called, common symbols do not belong to any section. // This function adds them to end of BSS section. template <class ELFT> @@ -495,12 +482,13 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) { // 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; + return A->Alignment > B->Alignment; }); - uintX_t Off = getBss()->getSize(); + uintX_t Off = Out<ELFT>::Bss->getSize(); for (DefinedCommon *C : Syms) { - Off = align(Off, C->MaxAlignment); + Off = alignTo(Off, C->Alignment); + Out<ELFT>::Bss->updateAlignment(C->Alignment); C->OffsetInBss = Off; Off += C->Size; } @@ -508,75 +496,16 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) { Out<ELFT>::Bss->setSize(Off); } -// Reserve space in .bss for copy relocations. -template <class ELFT> -void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) { - if (Syms.empty()) - return; - uintX_t Off = getBss()->getSize(); - for (SharedSymbol<ELFT> *C : Syms) { - const Elf_Sym &Sym = C->Sym; - const Elf_Shdr *Sec = C->File->getSection(Sym); - uintX_t SecAlign = Sec->sh_addralign; - unsigned TrailingZeros = - std::min(countTrailingZeros(SecAlign), - countTrailingZeros((uintX_t)Sym.st_value)); - uintX_t Align = 1 << TrailingZeros; - Out<ELFT>::Bss->updateAlign(Align); - Off = align(Off, Align); - C->OffsetInBss = Off; - Off += Sym.st_size; - } - Out<ELFT>::Bss->setSize(Off); -} - -template <class ELFT> -StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const { - auto It = InputToOutputSection.find(S); - if (It != std::end(InputToOutputSection)) - return It->second; - - if (S.startswith(".text.")) - return ".text"; - if (S.startswith(".rodata.")) - return ".rodata"; - if (S.startswith(".data.rel.ro")) - return ".data.rel.ro"; - if (S.startswith(".data.")) - return ".data"; - if (S.startswith(".bss.")) - return ".bss"; - return S; -} - -template <class ELFT> -void reportDiscarded(InputSectionBase<ELFT> *IS, - const std::unique_ptr<ObjectFile<ELFT>> &File) { - if (!Config->PrintGcSections || !IS || IS->isLive()) - return; - llvm::errs() << "removing unused section from '" << IS->getSectionName() - << "' in file '" << File->getName() << "'\n"; -} - template <class ELFT> -bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *IS) const { - if (!IS || !IS->isLive() || IS == &InputSection<ELFT>::Discarded) - return true; - return InputToOutputSection.lookup(IS->getSectionName()) == "/DISCARD/"; -} - -template <class ELFT> -static bool compareSections(OutputSectionBase<ELFT> *A, - OutputSectionBase<ELFT> *B) { - auto ItA = Config->OutputSections.find(A->getName()); - auto ItEnd = std::end(Config->OutputSections); - if (ItA == ItEnd) - return compareOutputSections(A, B); - auto ItB = Config->OutputSections.find(B->getName()); - if (ItB == ItEnd) - return compareOutputSections(A, B); - - return std::distance(ItA, ItB) > 0; +static Symbol *addOptionalSynthetic(SymbolTable<ELFT> &Table, StringRef Name, + OutputSectionBase<ELFT> *Sec, + typename ELFT::uint Val) { + SymbolBody *S = Table.find(Name); + if (!S) + return nullptr; + if (!S->isUndefined() && !S->isShared()) + return S->symbol(); + return Table.addSynthetic(Name, Sec, Val); } // The beginning and the ending of .rel[a].plt section are marked @@ -585,125 +514,57 @@ static bool compareSections(OutputSectionBase<ELFT> *A, // all IRELATIVE relocs on startup. For dynamic executables, we don't // need these symbols, since IRELATIVE relocs are resolved through GOT // and PLT. For details, see http://www.airs.com/blog/archives/403. -template <class ELFT> -void Writer<ELFT>::addRelIpltSymbols() { +template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { if (isOutputDynamic() || !Out<ELFT>::RelaPlt) return; - bool IsRela = shouldUseRela<ELFT>(); - - StringRef S = IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; - if (Symtab.find(S)) - Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltStart); - - S = IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; - if (Symtab.find(S)) - Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltEnd); -} - -template <class ELFT> static bool includeInSymtab(const SymbolBody &B) { - if (!B.isUsedInRegularObj()) - return false; - - // Don't include synthetic symbols like __init_array_start in every output. - if (auto *U = dyn_cast<DefinedRegular<ELFT>>(&B)) - if (&U->Sym == &ElfSym<ELFT>::IgnoredWeak || - &U->Sym == &ElfSym<ELFT>::Ignored) - return false; + StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start"; + addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt, 0); - return true; -} - -static bool includeInDynamicSymtab(const SymbolBody &B) { - uint8_t V = B.getVisibility(); - if (V != STV_DEFAULT && V != STV_PROTECTED) - return false; - if (Config->ExportDynamic || Config->Shared) - return true; - return B.isUsedInDynamicReloc(); -} - -// This class knows how to create an output section for a given -// input section. Output section type is determined by various -// factors, including input section's sh_flags, sh_type and -// linker scripts. -namespace { -template <class ELFT> class OutputSectionFactory { - typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; - typedef typename ELFFile<ELFT>::uintX_t uintX_t; - -public: - std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C, - StringRef OutsecName); - - OutputSectionBase<ELFT> *lookup(StringRef Name, uint32_t Type, uintX_t Flags); - -private: - SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C, - StringRef OutsecName); - - SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map; -}; -} - -template <class ELFT> -std::pair<OutputSectionBase<ELFT> *, bool> -OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C, - StringRef OutsecName) { - SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName); - OutputSectionBase<ELFT> *&Sec = Map[Key]; - if (Sec) - return {Sec, false}; - - switch (C->SectionKind) { - case InputSectionBase<ELFT>::Regular: - Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags); - break; - case InputSectionBase<ELFT>::EHFrame: - Sec = new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags); - break; - case InputSectionBase<ELFT>::Merge: - Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags); - break; - case InputSectionBase<ELFT>::MipsReginfo: - Sec = new MipsReginfoOutputSection<ELFT>(); - break; - } - return {Sec, true}; -} - -template <class ELFT> -OutputSectionBase<ELFT> *OutputSectionFactory<ELFT>::lookup(StringRef Name, - uint32_t Type, - uintX_t Flags) { - return Map.lookup({Name, Type, Flags, 0}); -} - -template <class ELFT> -SectionKey<ELFT::Is64Bits> -OutputSectionFactory<ELFT>::createKey(InputSectionBase<ELFT> *C, - StringRef OutsecName) { - const Elf_Shdr *H = C->getSectionHdr(); - uintX_t Flags = H->sh_flags & ~SHF_GROUP; - - // For SHF_MERGE we create different output sections for each sh_entsize. - // This makes each output section simple and keeps a single level - // mapping from input to output. - uintX_t EntSize = isa<MergeInputSection<ELFT>>(C) ? H->sh_entsize : 0; - - // GNU as can give .eh_frame secion type SHT_PROGBITS or SHT_X86_64_UNWIND - // depending on the construct. We want to canonicalize it so that - // there is only one .eh_frame in the end. - uint32_t Type = H->sh_type; - if (Type == SHT_PROGBITS && Config->EMachine == EM_X86_64 && - isa<EHInputSection<ELFT>>(C)) - Type = SHT_X86_64_UNWIND; - - return SectionKey<ELFT::Is64Bits>{OutsecName, Type, Flags, EntSize}; + S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end"; + addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt, + DefinedSynthetic<ELFT>::SectionEnd); } // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. template <class ELFT> void Writer<ELFT>::addReservedSymbols() { + if (Config->EMachine == EM_MIPS) { + // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer + // so that it points to an absolute address which is relative to GOT. + // See "Global Data Symbols" in Chapter 6 in the following document: + // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf + Symtab.addSynthetic("_gp", Out<ELFT>::Got, MipsGPOffset); + + // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between + // start of function and 'gp' pointer into GOT. + Symbol *Sym = + addOptionalSynthetic(Symtab, "_gp_disp", Out<ELFT>::Got, MipsGPOffset); + if (Sym) + ElfSym<ELFT>::MipsGpDisp = Sym->body(); + + // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' + // pointer. This symbol is used in the code generated by .cpload pseudo-op + // in case of using -mno-shared option. + // https://sourceware.org/ml/binutils/2004-12/msg00094.html + addOptionalSynthetic(Symtab, "__gnu_local_gp", Out<ELFT>::Got, + MipsGPOffset); + } + + // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol + // is magical and is used to produce a R_386_GOTPC relocation. + // The R_386_GOTPC relocation value doesn't actually depend on the + // symbol value, so it could use an index of STN_UNDEF which, according + // to the spec, means the symbol value is 0. + // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in + // the object file. + // The situation is even stranger on x86_64 where the assembly doesn't + // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as + // an undefined symbol in the .o files. + // Given that the symbol is effectively unused, we just create a dummy + // hidden one to avoid the undefined symbol error. + if (!Config->Relocatable) + Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_"); + // __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 @@ -711,35 +572,44 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() { if (!isOutputDynamic()) Symtab.addIgnored("__tls_get_addr"); - // If the "_end" symbol is referenced, it is expected to point to the address - // right after the data segment. Usually, this symbol points to the end - // of .bss section or to the end of .data section if .bss section is absent. - // The order of the sections can be affected by linker script, - // so it is hard to predict which section will be the last one. - // So, if this symbol is referenced, we just add the placeholder here - // and update its value later. - if (Symtab.find("_end")) - Symtab.addAbsolute("_end", ElfSym<ELFT>::End); - - // If there is an undefined symbol "end", we should initialize it - // with the same value as "_end". In any other case it should stay intact, - // because it is an allowable name for a user symbol. - if (SymbolBody *B = Symtab.find("end")) - if (B->isUndefined()) - Symtab.addAbsolute("end", ElfSym<ELFT>::End); + auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym1, + DefinedRegular<ELFT> *&Sym2) { + Sym1 = Symtab.addIgnored(S, STV_DEFAULT); + + // The name without the underscore is not a reserved name, + // so it is defined only when there is a reference against it. + assert(S.startswith("_")); + S = S.substr(1); + if (SymbolBody *B = Symtab.find(S)) + if (B->isUndefined()) + Sym2 = Symtab.addAbsolute(S, STV_DEFAULT); + }; + + Define("_end", ElfSym<ELFT>::End, ElfSym<ELFT>::End2); + Define("_etext", ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2); + Define("_edata", ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2); +} + +// Sort input sections by section name suffixes for +// __attribute__((init_priority(N))). +template <class ELFT> static void sortInitFini(OutputSectionBase<ELFT> *S) { + if (S) + reinterpret_cast<OutputSection<ELFT> *>(S)->sortInitFini(); +} + +// Sort input sections by the special rule for .ctors and .dtors. +template <class ELFT> static void sortCtorsDtors(OutputSectionBase<ELFT> *S) { + if (S) + reinterpret_cast<OutputSection<ELFT> *>(S)->sortCtorsDtors(); } // Create output section objects and add them to OutputSections. template <class ELFT> void Writer<ELFT>::createSections() { - // Add .interp first because some loaders want to see that section - // on the first page of the executable file when loaded into memory. - if (needsInterpSection()) - OutputSections.push_back(Out<ELFT>::Interp); - // Create output sections for input object file sections. std::vector<OutputSectionBase<ELFT> *> RegularSections; OutputSectionFactory<ELFT> Factory; - for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) { + for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F : + Symtab.getObjectFiles()) { for (InputSectionBase<ELFT> *C : F->getSections()) { if (isDiscarded(C)) { reportDiscarded(C, F); @@ -747,8 +617,7 @@ template <class ELFT> void Writer<ELFT>::createSections() { } OutputSectionBase<ELFT> *Sec; bool IsNew; - std::tie(Sec, IsNew) = - Factory.create(C, getOutputSectionName(C->getSectionName())); + std::tie(Sec, IsNew) = Factory.create(C, getOutputSectionName(C)); if (IsNew) { OwningSections.emplace_back(Sec); OutputSections.push_back(Sec); @@ -758,9 +627,6 @@ template <class ELFT> void Writer<ELFT>::createSections() { } } - Out<ELFT>::Bss = static_cast<OutputSection<ELFT> *>( - Factory.lookup(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE)); - // 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. @@ -773,56 +639,92 @@ template <class ELFT> void Writer<ELFT>::createSections() { Out<ELFT>::Dynamic->FiniArraySec = Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC); + // Sort section contents for __attribute__((init_priority(N)). + sortInitFini(Out<ELFT>::Dynamic->InitArraySec); + sortInitFini(Out<ELFT>::Dynamic->FiniArraySec); + sortCtorsDtors(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); + sortCtorsDtors(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); + // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop // symbols for sections, so that the runtime can get the start and end // addresses of each section by section name. Add such symbols. - addStartEndSymbols(); - for (OutputSectionBase<ELFT> *Sec : RegularSections) - addStartStopSymbols(Sec); + if (!Config->Relocatable) { + addStartEndSymbols(); + for (OutputSectionBase<ELFT> *Sec : RegularSections) + addStartStopSymbols(Sec); + } + + // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. + // It should be okay as no one seems to care about the type. + // Even the author of gold doesn't remember why gold behaves that way. + // https://sourceware.org/ml/binutils/2002-03/msg00360.html + if (isOutputDynamic()) + Symtab.addSynthetic("_DYNAMIC", Out<ELFT>::Dynamic, 0); + + // Define __rel[a]_iplt_{start,end} symbols if needed. + addRelIpltSymbols(); + + // Add scripted symbols with zero values now. + // Real values will be assigned later + Script<ELFT>::X->addScriptedSymbols(); + + if (!Out<ELFT>::EhFrame->empty()) { + OutputSections.push_back(Out<ELFT>::EhFrame); + Out<ELFT>::EhFrame->finalize(); + } // Scan relocations. This must be done after every symbol is declared so that // we can correctly decide if a dynamic relocation is needed. - for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) { + for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F : + Symtab.getObjectFiles()) { for (InputSectionBase<ELFT> *C : F->getSections()) { if (isDiscarded(C)) continue; - if (auto *S = dyn_cast<InputSection<ELFT>>(C)) - scanRelocs(*S); - else if (auto *S = dyn_cast<EHInputSection<ELFT>>(C)) + if (auto *S = dyn_cast<InputSection<ELFT>>(C)) { + scanRelocations(*S); + continue; + } + if (auto *S = dyn_cast<EhInputSection<ELFT>>(C)) if (S->RelocSection) - scanRelocs(*S, *S->RelocSection); + scanRelocations(*S, *S->RelocSection); } } - // Define __rel[a]_iplt_{start,end} symbols if needed. - addRelIpltSymbols(); + for (OutputSectionBase<ELFT> *Sec : OutputSections) + Sec->assignOffsets(); // Now that we have defined all possible symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. std::vector<DefinedCommon *> CommonSymbols; - std::vector<SharedSymbol<ELFT> *> CopyRelSymbols; - for (auto &P : Symtab.getSymbols()) { - SymbolBody *Body = P.second->Body; - if (auto *U = dyn_cast<Undefined>(Body)) - if (!U->isWeak() && !U->canKeepUndefined()) - reportUndefined<ELFT>(Symtab, Body); + for (Symbol *S : Symtab.getSymbols()) { + SymbolBody *Body = S->body(); + + // We only report undefined symbols in regular objects. This means that we + // will accept an undefined reference in bitcode if it can be optimized out. + if (S->IsUsedInRegularObj && Body->isUndefined() && !S->isWeak()) + reportUndefined<ELFT>(Symtab, Body); if (auto *C = dyn_cast<DefinedCommon>(Body)) CommonSymbols.push_back(C); - if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body)) - if (SC->NeedsCopy) - CopyRelSymbols.push_back(SC); if (!includeInSymtab<ELFT>(*Body)) continue; if (Out<ELFT>::SymTab) Out<ELFT>::SymTab->addSymbol(Body); - if (isOutputDynamic() && includeInDynamicSymtab(*Body)) + if (isOutputDynamic() && S->includeInDynsym()) { Out<ELFT>::DynSymTab->addSymbol(Body); + if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body)) + if (SS->file()->isNeeded()) + Out<ELFT>::VerNeed->addSymbol(SS); + } } + + // Do not proceed if there was an undefined symbol. + if (HasError) + return; + addCommonSymbols(CommonSymbols); - addCopyRelSymbols(CopyRelSymbols); // So far we have added sections from input object files. // This function adds linker-created Out<ELFT>::* sections. @@ -831,25 +733,47 @@ template <class ELFT> void Writer<ELFT>::createSections() { std::stable_sort(OutputSections.begin(), OutputSections.end(), compareSections<ELFT>); - for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) { - OutputSections[I]->SectionIndex = I + 1; - HasRelro |= (Config->ZRelro && isRelroSection(OutputSections[I])); + unsigned I = 1; + for (OutputSectionBase<ELFT> *Sec : OutputSections) { + Sec->SectionIndex = I++; + Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName())); } - for (OutputSectionBase<ELFT> *Sec : OutputSections) - Out<ELFT>::ShStrTab->reserve(Sec->getName()); - // Finalizers fix each section's size. - // .dynamic section's finalizer may add strings to .dynstr, - // so finalize that early. - // Likewise, .dynsym is finalized early since that may fill up .gnu.hash. - Out<ELFT>::Dynamic->finalize(); + // .dynsym is finalized early since that may fill up .gnu.hash. if (isOutputDynamic()) Out<ELFT>::DynSymTab->finalize(); - // Fill other section headers. + // Fill other section headers. The dynamic table is finalized + // at the end because some tags like RELSZ depend on result + // of finalizing other sections. The dynamic string table is + // finalized once the .dynamic finalizer has added a few last + // strings. See DynamicSection::finalize() + for (OutputSectionBase<ELFT> *Sec : OutputSections) + if (Sec != Out<ELFT>::DynStrTab && Sec != Out<ELFT>::Dynamic) + Sec->finalize(); + + if (isOutputDynamic()) + Out<ELFT>::Dynamic->finalize(); + + // Now that all output offsets are fixed. Finalize mergeable sections + // to fix their maps from input offsets to output offsets. for (OutputSectionBase<ELFT> *Sec : OutputSections) - Sec->finalize(); + Sec->finalizePieces(); +} + +template <class ELFT> bool Writer<ELFT>::needsGot() { + if (!Out<ELFT>::Got->empty()) + return true; + + // We add the .got section to the result for dynamic MIPS target because + // its address and properties are mentioned in the .dynamic section. + if (Config->EMachine == EM_MIPS) + return true; + + // If we have a relocation that is relative to GOT (such as GOTOFFREL), + // we need to emit a GOT even if it's empty. + return Out<ELFT>::Got->HasGotOffRel; } // This function add Out<ELFT>::* sections to OutputSections. @@ -859,6 +783,17 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { OutputSections.push_back(C); }; + // A core file does not usually contain unmodified segments except + // the first page of the executable. Add the build ID section to beginning of + // the file so that the section is included in the first page. + if (Out<ELFT>::BuildId) + OutputSections.insert(OutputSections.begin(), Out<ELFT>::BuildId); + + // Add .interp at first because some loaders want to see that section + // on the first page of the executable file when loaded into memory. + if (needsInterpSection()) + OutputSections.insert(OutputSections.begin(), Out<ELFT>::Interp); + // This order is not the same as the final output order // because we sort the sections using their attributes below. Add(Out<ELFT>::SymTab); @@ -866,25 +801,21 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { Add(Out<ELFT>::StrTab); if (isOutputDynamic()) { Add(Out<ELFT>::DynSymTab); + + bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0; + if (Out<ELFT>::VerDef || HasVerNeed) + Add(Out<ELFT>::VerSym); + Add(Out<ELFT>::VerDef); + if (HasVerNeed) + Add(Out<ELFT>::VerNeed); + Add(Out<ELFT>::GnuHashTab); Add(Out<ELFT>::HashTab); Add(Out<ELFT>::Dynamic); Add(Out<ELFT>::DynStrTab); if (Out<ELFT>::RelaDyn->hasRelocs()) Add(Out<ELFT>::RelaDyn); - - // This is a MIPS specific section to hold a space within the data segment - // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry. - // See "Dynamic section" in Chapter 5 in the following document: - // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - if (Config->EMachine == EM_MIPS && !Config->Shared) { - Out<ELFT>::MipsRldMap = new OutputSection<ELFT>(".rld_map", SHT_PROGBITS, - SHF_ALLOC | SHF_WRITE); - Out<ELFT>::MipsRldMap->setSize(ELFT::Is64Bits ? 8 : 4); - Out<ELFT>::MipsRldMap->updateAlign(ELFT::Is64Bits ? 8 : 4); - OwningSections.emplace_back(Out<ELFT>::MipsRldMap); - Add(Out<ELFT>::MipsRldMap); - } + Add(Out<ELFT>::MipsRldMap); } // We always need to add rel[a].plt to output if it has entries. @@ -894,22 +825,16 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { Out<ELFT>::RelaPlt->Static = !isOutputDynamic(); } - bool needsGot = !Out<ELFT>::Got->empty(); - // We add the .got section to the result for dynamic MIPS target because - // its address and properties are mentioned in the .dynamic section. - if (Config->EMachine == EM_MIPS) - needsGot |= isOutputDynamic(); - // If we have a relocation that is relative to GOT (such as GOTOFFREL), - // we need to emit a GOT even if it's empty. - if (HasGotOffRel) - needsGot = true; - - if (needsGot) + if (needsGot()) Add(Out<ELFT>::Got); if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty()) Add(Out<ELFT>::GotPlt); if (!Out<ELFT>::Plt->empty()) Add(Out<ELFT>::Plt); + if (!Out<ELFT>::EhFrame->empty()) + Add(Out<ELFT>::EhFrameHdr); + if (Out<ELFT>::Bss->getSize() > 0) + Add(Out<ELFT>::Bss); } // The linker is expected to define SECNAME_start and SECNAME_end @@ -918,11 +843,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { auto Define = [&](StringRef Start, StringRef End, OutputSectionBase<ELFT> *OS) { if (OS) { - Symtab.addSynthetic(Start, *OS, 0); - Symtab.addSynthetic(End, *OS, OS->getSize()); + this->Symtab.addSynthetic(Start, OS, 0); + this->Symtab.addSynthetic(End, OS, DefinedSynthetic<ELFT>::SectionEnd); } else { - Symtab.addIgnored(Start); - Symtab.addIgnored(End); + addOptionalSynthetic(this->Symtab, Start, + (OutputSectionBase<ELFT> *)nullptr, 0); + addOptionalSynthetic(this->Symtab, End, + (OutputSectionBase<ELFT> *)nullptr, 0); } }; @@ -934,19 +861,6 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { Out<ELFT>::Dynamic->FiniArraySec); } -static bool isAlpha(char C) { - return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_'; -} - -static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); } - -// Returns true if S is valid as a C language identifier. -static bool isValidCIdentifier(StringRef S) { - if (S.empty() || !isAlpha(S[0])) - return false; - return std::all_of(S.begin() + 1, S.end(), isAlnum); -} - // If a section name is valid as a C identifier (which is rare because of // the leading '.'), linkers are expected to define __start_<secname> and // __stop_<secname> symbols. They are at beginning and end of the section, @@ -962,14 +876,22 @@ void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) { StringRef Stop = Saver.save("__stop_" + S); if (SymbolBody *B = Symtab.find(Start)) if (B->isUndefined()) - Symtab.addSynthetic(Start, *Sec, 0); + Symtab.addSynthetic(Start, Sec, 0); if (SymbolBody *B = Symtab.find(Stop)) if (B->isUndefined()) - Symtab.addSynthetic(Stop, *Sec, Sec->getSize()); + Symtab.addSynthetic(Stop, Sec, DefinedSynthetic<ELFT>::SectionEnd); } -template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) { - return Sec->getFlags() & SHF_ALLOC; +template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) { + if (!(Sec->getFlags() & SHF_ALLOC)) + return false; + + // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is + // responsible for allocating space for them, not the PT_LOAD that + // contains the TLS initialization image. + if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) + return false; + return true; } static uint32_t toPhdrFlags(uint64_t Flags) { @@ -981,269 +903,341 @@ static uint32_t toPhdrFlags(uint64_t Flags) { return Ret; } -/// For AMDGPU we need to use custom segment kinds in order to specify which -/// address space data should be loaded into. -template <class ELFT> -static uint32_t getAmdgpuPhdr(OutputSectionBase<ELFT> *Sec) { - uint32_t Flags = Sec->getFlags(); - if (Flags & SHF_AMDGPU_HSA_CODE) - return PT_AMDGPU_HSA_LOAD_CODE_AGENT; - if ((Flags & SHF_AMDGPU_HSA_GLOBAL) && !(Flags & SHF_AMDGPU_HSA_AGENT)) - return PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM; - return PT_LOAD; -} - -template <class ELFT> -void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, - uintX_t VA) { - if (!GnuRelroPhdr->p_type) - setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr, - VA - Cur->p_vaddr, 1 /*p_align*/); - GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr; - GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr; -} - -// Visits all sections to create PHDRs and to assign incremental, -// non-overlapping addresses to output sections. -template <class ELFT> void Writer<ELFT>::assignAddresses() { - uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr); - uintX_t FileOff = sizeof(Elf_Ehdr); +// Decide which program headers to create and which sections to include in each +// one. +template <class ELFT> void Writer<ELFT>::createPhdrs() { + auto AddHdr = [this](unsigned Type, unsigned Flags) { + return &*Phdrs.emplace(Phdrs.end(), Type, Flags); + }; - // Calculate and reserve the space for the program header first so that - // the first section can start right after the program header. - Phdrs.resize(getPhdrsNum()); - size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size(); + auto AddSec = [](Phdr &Hdr, OutputSectionBase<ELFT> *Sec) { + Hdr.Last = Sec; + if (!Hdr.First) + Hdr.First = Sec; + Hdr.H.p_align = std::max<uintX_t>(Hdr.H.p_align, Sec->getAlignment()); + }; // The first phdr entry is PT_PHDR which describes the program header itself. - setPhdr(&Phdrs[0], PT_PHDR, PF_R, FileOff, VA, PhdrSize, /*Align=*/8); - FileOff += PhdrSize; - VA += PhdrSize; + Phdr &Hdr = *AddHdr(PT_PHDR, PF_R); + AddSec(Hdr, Out<ELFT>::ProgramHeaders); // PT_INTERP must be the second entry if exists. - int PhdrIdx = 0; - Elf_Phdr *Interp = nullptr; - if (needsInterpSection()) - Interp = &Phdrs[++PhdrIdx]; + if (needsInterpSection()) { + Phdr &Hdr = *AddHdr(PT_INTERP, toPhdrFlags(Out<ELFT>::Interp->getFlags())); + AddSec(Hdr, Out<ELFT>::Interp); + } // Add the first PT_LOAD segment for regular output sections. - setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff, - Target->getPageSize()); - - Elf_Phdr GnuRelroPhdr = {}; - Elf_Phdr TlsPhdr{}; - bool RelroAligned = false; - uintX_t ThreadBssOffset = 0; - // Create phdrs as we assign VAs and file offsets to all output sections. + uintX_t Flags = PF_R; + Phdr *Load = AddHdr(PT_LOAD, Flags); + AddSec(*Load, Out<ELFT>::ElfHeader); + AddSec(*Load, Out<ELFT>::ProgramHeaders); + + Phdr TlsHdr(PT_TLS, PF_R); + Phdr RelRo(PT_GNU_RELRO, PF_R); + Phdr Note(PT_NOTE, PF_R); for (OutputSectionBase<ELFT> *Sec : OutputSections) { - Elf_Phdr *PH = &Phdrs[PhdrIdx]; - if (needsPhdr<ELFT>(Sec)) { - uintX_t Flags = toPhdrFlags(Sec->getFlags()); - bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec); - bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned; - if (FirstNonRelRo || PH->p_flags != Flags) { - VA = align(VA, Target->getPageSize()); - FileOff = align(FileOff, Target->getPageSize()); - if (FirstNonRelRo) - RelroAligned = true; - } + if (!(Sec->getFlags() & SHF_ALLOC)) + break; - if (PH->p_flags != Flags) { - // Flags changed. Create a new PT_LOAD. - PH = &Phdrs[++PhdrIdx]; - uint32_t PTType = (Config->EMachine != EM_AMDGPU) ? (uint32_t)PT_LOAD - : getAmdgpuPhdr(Sec); - setPhdr(PH, PTType, Flags, FileOff, VA, 0, Target->getPageSize()); - } + // If we meet TLS section then we create TLS header + // and put all TLS sections inside for futher use when + // assign addresses. + if (Sec->getFlags() & SHF_TLS) + AddSec(TlsHdr, Sec); - if (Sec->getFlags() & SHF_TLS) { - if (!TlsPhdr.p_vaddr) - setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign()); - if (Sec->getType() != SHT_NOBITS) - VA = align(VA, Sec->getAlign()); - uintX_t TVA = align(VA + ThreadBssOffset, Sec->getAlign()); - Sec->setVA(TVA); - TlsPhdr.p_memsz += Sec->getSize(); - if (Sec->getType() == SHT_NOBITS) { - ThreadBssOffset = TVA - VA + Sec->getSize(); - } else { - TlsPhdr.p_filesz += Sec->getSize(); - VA += Sec->getSize(); - } - TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign()); - } else { - VA = align(VA, Sec->getAlign()); - Sec->setVA(VA); - VA += Sec->getSize(); - if (InRelRo) - updateRelro(PH, &GnuRelroPhdr, VA); - } - } + if (!needsPtLoad<ELFT>(Sec)) + continue; - FileOff = align(FileOff, Sec->getAlign()); - Sec->setFileOffset(FileOff); - if (Sec->getType() != SHT_NOBITS) - FileOff += Sec->getSize(); - if (needsPhdr<ELFT>(Sec)) { - PH->p_filesz = FileOff - PH->p_offset; - PH->p_memsz = VA - PH->p_vaddr; + // If flags changed then we want new load segment. + uintX_t NewFlags = toPhdrFlags(Sec->getFlags()); + if (Flags != NewFlags) { + Load = AddHdr(PT_LOAD, NewFlags); + Flags = NewFlags; } - } - if (TlsPhdr.p_vaddr) { - // The TLS pointer goes after PT_TLS. At least glibc will align it, - // so round up the size to make sure the offsets are correct. - TlsPhdr.p_memsz = align(TlsPhdr.p_memsz, TlsPhdr.p_align); - Phdrs[++PhdrIdx] = TlsPhdr; - Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx]; + AddSec(*Load, Sec); + + if (isRelroSection(Sec)) + AddSec(RelRo, Sec); + if (Sec->getType() == SHT_NOTE) + AddSec(Note, Sec); } + // Add the TLS segment unless it's empty. + if (TlsHdr.First) + Phdrs.push_back(std::move(TlsHdr)); + // Add an entry for .dynamic. if (isOutputDynamic()) { - Elf_Phdr *PH = &Phdrs[++PhdrIdx]; - PH->p_type = PT_DYNAMIC; - copyPhdr(PH, Out<ELFT>::Dynamic); + Phdr &H = *AddHdr(PT_DYNAMIC, toPhdrFlags(Out<ELFT>::Dynamic->getFlags())); + AddSec(H, Out<ELFT>::Dynamic); } - if (HasRelro) { - Elf_Phdr *PH = &Phdrs[++PhdrIdx]; - *PH = GnuRelroPhdr; + // PT_GNU_RELRO includes all sections that should be marked as + // read-only by dynamic linker after proccessing relocations. + if (RelRo.First) + Phdrs.push_back(std::move(RelRo)); + + // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. + if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr) { + Phdr &Hdr = *AddHdr(PT_GNU_EH_FRAME, + toPhdrFlags(Out<ELFT>::EhFrameHdr->getFlags())); + AddSec(Hdr, Out<ELFT>::EhFrameHdr); } // PT_GNU_STACK is a special section to tell the loader to make the // pages for the stack non-executable. - if (!Config->ZExecStack) { - Elf_Phdr *PH = &Phdrs[++PhdrIdx]; - PH->p_type = PT_GNU_STACK; - PH->p_flags = PF_R | PF_W; + if (!Config->ZExecStack) + AddHdr(PT_GNU_STACK, PF_R | PF_W); + + if (Note.First) + Phdrs.push_back(std::move(Note)); + + Out<ELFT>::ProgramHeaders->setSize(sizeof(Elf_Phdr) * Phdrs.size()); +} + +// The first section of each PT_LOAD and the first section after PT_GNU_RELRO +// have to be page aligned so that the dynamic linker can set the permissions. +template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { + for (const Phdr &P : Phdrs) + if (P.H.p_type == PT_LOAD) + P.First->PageAlign = true; + + for (const Phdr &P : Phdrs) { + if (P.H.p_type != PT_GNU_RELRO) + continue; + // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we + // have to align it to a page. + auto End = OutputSections.end(); + auto I = std::find(OutputSections.begin(), End, P.Last); + if (I == End || (I + 1) == End) + continue; + OutputSectionBase<ELFT> *Sec = *(I + 1); + if (needsPtLoad(Sec)) + Sec->PageAlign = true; } +} - // Fix up PT_INTERP as we now know the address of .interp section. - if (Interp) { - Interp->p_type = PT_INTERP; - copyPhdr(Interp, Out<ELFT>::Interp); +// We should set file offsets and VAs for elf header and program headers +// sections. These are special, we do not include them into output sections +// list, but have them to simplify the code. +template <class ELFT> void Writer<ELFT>::fixHeaders() { + uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Config->ImageBase; + Out<ELFT>::ElfHeader->setVA(BaseVA); + uintX_t Off = Out<ELFT>::ElfHeader->getSize(); + Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA); +} + +// Assign VAs (addresses at run-time) to output sections. +template <class ELFT> void Writer<ELFT>::assignAddresses() { + uintX_t VA = Config->ImageBase + Out<ELFT>::ElfHeader->getSize() + + Out<ELFT>::ProgramHeaders->getSize(); + + uintX_t ThreadBssOffset = 0; + for (OutputSectionBase<ELFT> *Sec : OutputSections) { + uintX_t Alignment = Sec->getAlignment(); + if (Sec->PageAlign) + Alignment = std::max<uintX_t>(Alignment, Target->PageSize); + + // We only assign VAs to allocated sections. + if (needsPtLoad<ELFT>(Sec)) { + VA = alignTo(VA, Alignment); + Sec->setVA(VA); + VA += Sec->getSize(); + } else if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) { + uintX_t TVA = VA + ThreadBssOffset; + TVA = alignTo(TVA, Alignment); + Sec->setVA(TVA); + ThreadBssOffset = TVA - VA + Sec->getSize(); + } } +} + +// Adjusts the file alignment for a given output section and returns +// its new file offset. The file offset must be the same with its +// virtual address (modulo the page size) so that the loader can load +// executables without any address adjustment. +template <class ELFT, class uintX_t> +static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) { + uintX_t Alignment = Sec->getAlignment(); + if (Sec->PageAlign) + Alignment = std::max<uintX_t>(Alignment, Target->PageSize); + Off = alignTo(Off, Alignment); + + // Relocatable output does not have program headers + // and does not need any other offset adjusting. + if (Config->Relocatable || !(Sec->getFlags() & SHF_ALLOC)) + return Off; + return alignTo(Off, Target->PageSize, Sec->getVA()); +} + +// Assign file offsets to output sections. +template <class ELFT> void Writer<ELFT>::assignFileOffsets() { + uintX_t Off = 0; - // Add space for section headers. - SectionHeaderOff = align(FileOff, ELFT::Is64Bits ? 8 : 4); - FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr); + auto Set = [&](OutputSectionBase<ELFT> *Sec) { + if (Sec->getType() == SHT_NOBITS) { + Sec->setFileOffset(Off); + return; + } - // Update "_end" and "end" symbols so that they - // point to the end of the data segment. - ElfSym<ELFT>::End.st_value = VA; + Off = getFileAlignment<ELFT>(Off, Sec); + Sec->setFileOffset(Off); + Off += Sec->getSize(); + }; + + Set(Out<ELFT>::ElfHeader); + Set(Out<ELFT>::ProgramHeaders); + for (OutputSectionBase<ELFT> *Sec : OutputSections) + Set(Sec); + + SectionHeaderOff = alignTo(Off, sizeof(uintX_t)); + FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr); } -// Returns the number of PHDR entries. -template <class ELFT> int Writer<ELFT>::getPhdrsNum() const { - bool Tls = false; - int I = 2; // 2 for PT_PHDR and first PT_LOAD - if (needsInterpSection()) - ++I; - if (isOutputDynamic()) - ++I; - if (!Config->ZExecStack) - ++I; - uintX_t Last = PF_R; - for (OutputSectionBase<ELFT> *Sec : OutputSections) { - if (!needsPhdr<ELFT>(Sec)) - continue; - if (Sec->getFlags() & SHF_TLS) - Tls = true; - uintX_t Flags = toPhdrFlags(Sec->getFlags()); - if (Last != Flags) { - Last = Flags; - ++I; +// Finalize the program headers. We call this function after we assign +// file offsets and VAs to all sections. +template <class ELFT> void Writer<ELFT>::setPhdrs() { + for (Phdr &P : Phdrs) { + Elf_Phdr &H = P.H; + OutputSectionBase<ELFT> *First = P.First; + OutputSectionBase<ELFT> *Last = P.Last; + if (First) { + H.p_filesz = Last->getFileOff() - First->getFileOff(); + if (Last->getType() != SHT_NOBITS) + H.p_filesz += Last->getSize(); + H.p_memsz = Last->getVA() + Last->getSize() - First->getVA(); + H.p_offset = First->getFileOff(); + H.p_vaddr = First->getVA(); + } + if (H.p_type == PT_LOAD) + H.p_align = Target->PageSize; + else if (H.p_type == PT_GNU_RELRO) + H.p_align = 1; + H.p_paddr = H.p_vaddr; + + // The TLS pointer goes after PT_TLS. At least glibc will align it, + // so round up the size to make sure the offsets are correct. + if (H.p_type == PT_TLS) { + Out<ELFT>::TlsPhdr = &H; + H.p_memsz = alignTo(H.p_memsz, H.p_align); } } - if (Tls) - ++I; - if (HasRelro) - ++I; - return I; } -static uint32_t getELFFlags() { - if (Config->EMachine != EM_MIPS) - return 0; +static uint32_t getMipsEFlags(bool Is64Bits) { // FIXME: In fact ELF flags depends on ELF flags of input object files // and selected emulation. For now just use hard coded values. - uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | EF_MIPS_ARCH_32R2; + if (Is64Bits) + return EF_MIPS_CPIC | EF_MIPS_PIC | EF_MIPS_ARCH_64R2; + + uint32_t V = EF_MIPS_CPIC | EF_MIPS_ABI_O32 | EF_MIPS_ARCH_32R2; if (Config->Shared) V |= EF_MIPS_PIC; return V; } -template <class ELFT> -static typename ELFFile<ELFT>::uintX_t getEntryAddr() { - if (Config->EntrySym) { - if (SymbolBody *E = Config->EntrySym->repl()) - return getSymVA<ELFT>(*E); - return 0; - } +template <class ELFT> static typename ELFT::uint getEntryAddr() { + if (Symbol *S = Config->EntrySym) + return S->body()->getVA<ELFT>(); if (Config->EntryAddr != uint64_t(-1)) return Config->EntryAddr; return 0; } +template <class ELFT> static uint8_t getELFEncoding() { + if (ELFT::TargetEndianness == llvm::support::little) + return ELFDATA2LSB; + return ELFDATA2MSB; +} + +static uint16_t getELFType() { + if (Config->Pic) + return ET_DYN; + if (Config->Relocatable) + return ET_REL; + return ET_EXEC; +} + // This function is called after we have assigned address and size // to each section. This function fixes some predefined absolute // symbol values that depend on section address and size. template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() { - // Update __rel[a]_iplt_{start,end} symbols so that they point - // to beginning or ending of .rela.plt section, respectively. - if (Out<ELFT>::RelaPlt) { - uintX_t Start = Out<ELFT>::RelaPlt->getVA(); - ElfSym<ELFT>::RelaIpltStart.st_value = Start; - ElfSym<ELFT>::RelaIpltEnd.st_value = Start + Out<ELFT>::RelaPlt->getSize(); - } + auto Set = [](DefinedRegular<ELFT> *S1, DefinedRegular<ELFT> *S2, uintX_t V) { + if (S1) + S1->Value = V; + if (S2) + S2->Value = V; + }; - // Update MIPS _gp absolute symbol so that it points to the static data. - if (Config->EMachine == EM_MIPS) - ElfSym<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>(); + // _etext is the first location after the last read-only loadable segment. + // _edata is the first location after the last read-write loadable segment. + // _end is the first location after the uninitialized data region. + for (Phdr &P : Phdrs) { + Elf_Phdr &H = P.H; + if (H.p_type != PT_LOAD) + continue; + Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, H.p_vaddr + H.p_memsz); + + uintX_t Val = H.p_vaddr + H.p_filesz; + if (H.p_flags & PF_W) + Set(ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2, Val); + else + Set(ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2, Val); + } } template <class ELFT> void Writer<ELFT>::writeHeader() { uint8_t *Buf = Buffer->getBufferStart(); memcpy(Buf, "\177ELF", 4); + auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf); + // Write the ELF header. auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf); 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_DATA] = getELFEncoding<ELFT>(); EHdr->e_ident[EI_VERSION] = EV_CURRENT; - - auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf); EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI(); - - EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC; - EHdr->e_machine = FirstObj.getEMachine(); + EHdr->e_type = getELFType(); + EHdr->e_machine = FirstObj.EMachine; EHdr->e_version = EV_CURRENT; EHdr->e_entry = getEntryAddr<ELFT>(); - EHdr->e_phoff = sizeof(Elf_Ehdr); EHdr->e_shoff = SectionHeaderOff; - EHdr->e_flags = getELFFlags(); 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_shnum = OutputSections.size() + 1; EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex; + if (Config->EMachine == EM_MIPS) + EHdr->e_flags = getMipsEFlags(ELFT::Is64Bits); + + if (!Config->Relocatable) { + EHdr->e_phoff = sizeof(Elf_Ehdr); + EHdr->e_phentsize = sizeof(Elf_Phdr); + } + // Write the program header table. - memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0])); + auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff); + for (Phdr &P : Phdrs) + *HBuf++ = P.H; // Write the section header table. Note that the first table entry is null. - auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff); + auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff); for (OutputSectionBase<ELFT> *Sec : OutputSections) Sec->writeHeaderTo(++SHdrs); } -template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) { +template <class ELFT> void Writer<ELFT>::openFile() { ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = - FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable); - error(BufferOrErr, "failed to open " + Path); - Buffer = std::move(*BufferOrErr); + FileOutputBuffer::create(Config->OutputFile, FileSize, + FileOutputBuffer::F_executable); + if (auto EC = BufferOrErr.getError()) + error(EC, "failed to open " + Config->OutputFile); + else + Buffer = std::move(*BufferOrErr); } // Write section contents to a mmap'ed file. @@ -1257,53 +1251,33 @@ template <class ELFT> void Writer<ELFT>::writeSections() { Sec->writeTo(Buf + Sec->getFileOff()); } - // Write all sections but string table sections. We know the sizes of the - // string tables already, but they may not have actual strings yet (only - // room may be reserved), because writeTo() is allowed to add actual - // strings to the string tables. for (OutputSectionBase<ELFT> *Sec : OutputSections) - if (Sec != Out<ELFT>::Opd && Sec->getType() != SHT_STRTAB) + if (Sec != Out<ELFT>::Opd) Sec->writeTo(Buf + Sec->getFileOff()); - - // Write string table sections. - for (OutputSectionBase<ELFT> *Sec : OutputSections) - if (Sec != Out<ELFT>::Opd && Sec->getType() == SHT_STRTAB) - Sec->writeTo(Buf + Sec->getFileOff()); -} - -template <class ELFT> -void Writer<ELFT>::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, - uintX_t FileOff, uintX_t VA, uintX_t Size, - 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_filesz = Size; - PH->p_memsz = Size; - PH->p_align = Align; } -template <class ELFT> -void Writer<ELFT>::copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *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 <class ELFT> void Writer<ELFT>::writeBuildId() { + if (!Out<ELFT>::BuildId) + return; -template <class ELFT> void Writer<ELFT>::buildSectionMap() { - for (const std::pair<StringRef, std::vector<StringRef>> &OutSec : - Config->OutputSections) - for (StringRef Name : OutSec.second) - InputToOutputSection[Name] = OutSec.first; + // Compute a hash of all sections except .debug_* sections. + // We skip debug sections because they tend to be very large + // and their contents are very likely to be the same as long as + // other sections are the same. + uint8_t *Start = Buffer->getBufferStart(); + uint8_t *Last = Start; + std::vector<ArrayRef<uint8_t>> Regions; + for (OutputSectionBase<ELFT> *Sec : OutputSections) { + uint8_t *End = Start + Sec->getFileOff(); + if (!Sec->getName().startswith(".debug_")) + Regions.push_back({Last, End}); + Last = End; + } + Regions.push_back({Last, Start + FileSize}); + Out<ELFT>::BuildId->writeBuildId(Regions); } -template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab); -template void elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab); -template void elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab); -template void elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab); +template void elf::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab); +template void elf::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab); +template void elf::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab); +template void elf::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab); |