diff options
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r-- | ELF/Writer.cpp | 697 |
1 files changed, 410 insertions, 287 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 73a97380b54b1..17f4c7961d30e 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -53,8 +53,10 @@ private: void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> Fn); void sortSections(); void resolveShfLinkOrder(); + void maybeAddThunks(); void sortInputSections(); void finalizeSections(); + void checkExecuteOnly(); void setReservedSymbolSections(); std::vector<PhdrEntry *> createPhdrs(); @@ -77,7 +79,6 @@ private: void addRelIpltSymbols(); void addStartEndSymbols(); void addStartStopSymbols(OutputSection *Sec); - uint64_t getEntryAddr(); std::vector<PhdrEntry *> Phdrs; @@ -114,18 +115,16 @@ StringRef elf::getOutputSectionName(const InputSectionBase *S) { // for instance. if (Config->ZKeepTextSectionPrefix) for (StringRef V : - {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) { + {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) if (isSectionPrefix(V, S->Name)) return V.drop_back(); - } for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", - ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) { + ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) if (isSectionPrefix(V, S->Name)) return V.drop_back(); - } // CommonSection is identified as "COMMON" in linker scripts. // By default, it should go to .bss section. @@ -159,7 +158,7 @@ template <class ELFT> static void combineEhFrameSections() { if (!ES || !ES->Live) continue; - InX::EhFrame->addSection<ELFT>(ES); + In.EhFrame->addSection<ELFT>(ES); S = nullptr; } @@ -173,10 +172,14 @@ static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec, Symbol *S = Symtab->find(Name); if (!S || S->isDefined()) return nullptr; - Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, - /*Size=*/0, Binding, Sec, - /*File=*/nullptr); - return cast<Defined>(Sym); + return Symtab->addDefined(Name, StOther, STT_NOTYPE, Val, + /*Size=*/0, Binding, Sec, + /*File=*/nullptr); +} + +static Defined *addAbsolute(StringRef Name) { + return Symtab->addDefined(Name, STV_HIDDEN, STT_NOTYPE, 0, 0, STB_GLOBAL, + nullptr, nullptr); } // The linker is expected to define some symbols depending on @@ -188,21 +191,19 @@ void elf::addReservedSymbols() { // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL); + ElfSym::MipsGp = addAbsolute("_gp"); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. if (Symtab->find("_gp_disp")) - ElfSym::MipsGpDisp = - Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL); + ElfSym::MipsGpDisp = addAbsolute("_gp_disp"); // 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 if (Symtab->find("__gnu_local_gp")) - ElfSym::MipsLocalGp = - Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL); + ElfSym::MipsLocalGp = addAbsolute("__gnu_local_gp"); } // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which @@ -211,9 +212,20 @@ void elf::addReservedSymbols() { // _GLOBAL_OFFSET_TABLE_ and _SDA_BASE_ from the 32-bit ABI. It is used to // represent the TOC base which is offset by 0x8000 bytes from the start of // the .got section. - ElfSym::GlobalOffsetTable = addOptionalRegular( - (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_", - Out::ElfHeader, Target->GotBaseSymOff); + // We do not allow _GLOBAL_OFFSET_TABLE_ to be defined by input objects as the + // correctness of some relocations depends on its value. + StringRef GotTableSymName = + (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_"; + if (Symbol *S = Symtab->find(GotTableSymName)) { + if (S->isDefined()) + error(toString(S->File) + " cannot redefine linker defined symbol '" + + GotTableSymName + "'"); + else + ElfSym::GlobalOffsetTable = Symtab->addDefined( + GotTableSymName, STV_HIDDEN, STT_NOTYPE, Target->GotBaseSymOff, + /*Size=*/0, STB_GLOBAL, Out::ElfHeader, + /*File=*/nullptr); + } // __ehdr_start is the location of ELF file headers. Note that we define // this symbol unconditionally even when using a linker script, which @@ -263,54 +275,52 @@ template <class ELFT> static void createSyntheticSections() { auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); }; - InX::DynStrTab = make<StringTableSection>(".dynstr", true); - InX::Dynamic = make<DynamicSection<ELFT>>(); + In.DynStrTab = make<StringTableSection>(".dynstr", true); + In.Dynamic = make<DynamicSection<ELFT>>(); if (Config->AndroidPackDynRelocs) { - InX::RelaDyn = make<AndroidPackedRelocationSection<ELFT>>( + In.RelaDyn = make<AndroidPackedRelocationSection<ELFT>>( Config->IsRela ? ".rela.dyn" : ".rel.dyn"); } else { - InX::RelaDyn = make<RelocationSection<ELFT>>( + In.RelaDyn = make<RelocationSection<ELFT>>( Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); } - InX::ShStrTab = make<StringTableSection>(".shstrtab", false); + In.ShStrTab = make<StringTableSection>(".shstrtab", false); Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC); Out::ProgramHeaders->Alignment = Config->Wordsize; if (needsInterpSection()) { - InX::Interp = createInterpSection(); - Add(InX::Interp); - } else { - InX::Interp = nullptr; + In.Interp = createInterpSection(); + Add(In.Interp); } if (Config->Strip != StripPolicy::All) { - InX::StrTab = make<StringTableSection>(".strtab", false); - InX::SymTab = make<SymbolTableSection<ELFT>>(*InX::StrTab); - InX::SymTabShndx = make<SymtabShndxSection>(); + In.StrTab = make<StringTableSection>(".strtab", false); + In.SymTab = make<SymbolTableSection<ELFT>>(*In.StrTab); + In.SymTabShndx = make<SymtabShndxSection>(); } if (Config->BuildId != BuildIdKind::None) { - InX::BuildId = make<BuildIdSection>(); - Add(InX::BuildId); + In.BuildId = make<BuildIdSection>(); + Add(In.BuildId); } - InX::Bss = make<BssSection>(".bss", 0, 1); - Add(InX::Bss); + In.Bss = make<BssSection>(".bss", 0, 1); + Add(In.Bss); // If there is a SECTIONS command and a .data.rel.ro section name use name // .data.rel.ro.bss so that we match in the .data.rel.ro output section. // This makes sure our relro is contiguous. bool HasDataRelRo = Script->HasSectionsCommand && findSection(".data.rel.ro"); - InX::BssRelRo = + In.BssRelRo = make<BssSection>(HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1); - Add(InX::BssRelRo); + Add(In.BssRelRo); // Add MIPS-specific sections. if (Config->EMachine == EM_MIPS) { if (!Config->Shared && Config->HasDynSymTab) { - InX::MipsRldMap = make<MipsRldMapSection>(); - Add(InX::MipsRldMap); + In.MipsRldMap = make<MipsRldMapSection>(); + Add(In.MipsRldMap); } if (auto *Sec = MipsAbiFlagsSection<ELFT>::create()) Add(Sec); @@ -321,65 +331,70 @@ template <class ELFT> static void createSyntheticSections() { } if (Config->HasDynSymTab) { - InX::DynSymTab = make<SymbolTableSection<ELFT>>(*InX::DynStrTab); - Add(InX::DynSymTab); + In.DynSymTab = make<SymbolTableSection<ELFT>>(*In.DynStrTab); + Add(In.DynSymTab); - In<ELFT>::VerSym = make<VersionTableSection<ELFT>>(); - Add(In<ELFT>::VerSym); + InX<ELFT>::VerSym = make<VersionTableSection<ELFT>>(); + Add(InX<ELFT>::VerSym); if (!Config->VersionDefinitions.empty()) { - In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>(); - Add(In<ELFT>::VerDef); + In.VerDef = make<VersionDefinitionSection>(); + Add(In.VerDef); } - In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>(); - Add(In<ELFT>::VerNeed); + InX<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>(); + Add(InX<ELFT>::VerNeed); if (Config->GnuHash) { - InX::GnuHashTab = make<GnuHashTableSection>(); - Add(InX::GnuHashTab); + In.GnuHashTab = make<GnuHashTableSection>(); + Add(In.GnuHashTab); } if (Config->SysvHash) { - InX::HashTab = make<HashTableSection>(); - Add(InX::HashTab); + In.HashTab = make<HashTableSection>(); + Add(In.HashTab); } - Add(InX::Dynamic); - Add(InX::DynStrTab); - Add(InX::RelaDyn); + Add(In.Dynamic); + Add(In.DynStrTab); + Add(In.RelaDyn); } if (Config->RelrPackDynRelocs) { - InX::RelrDyn = make<RelrSection<ELFT>>(); - Add(InX::RelrDyn); + In.RelrDyn = make<RelrSection<ELFT>>(); + Add(In.RelrDyn); } // Add .got. MIPS' .got is so different from the other archs, // it has its own class. if (Config->EMachine == EM_MIPS) { - InX::MipsGot = make<MipsGotSection>(); - Add(InX::MipsGot); + In.MipsGot = make<MipsGotSection>(); + Add(In.MipsGot); } else { - InX::Got = make<GotSection>(); - Add(InX::Got); + In.Got = make<GotSection>(); + Add(In.Got); } - InX::GotPlt = make<GotPltSection>(); - Add(InX::GotPlt); - InX::IgotPlt = make<IgotPltSection>(); - Add(InX::IgotPlt); + if (Config->EMachine == EM_PPC64) { + In.PPC64LongBranchTarget = make<PPC64LongBranchTargetSection>(); + Add(In.PPC64LongBranchTarget); + } + + In.GotPlt = make<GotPltSection>(); + Add(In.GotPlt); + In.IgotPlt = make<IgotPltSection>(); + Add(In.IgotPlt); if (Config->GdbIndex) { - InX::GdbIndex = GdbIndexSection::create<ELFT>(); - Add(InX::GdbIndex); + In.GdbIndex = GdbIndexSection::create<ELFT>(); + Add(In.GdbIndex); } // We always need to add rel[a].plt to output if it has entries. // Even for static linking it can contain R_[*]_IRELATIVE relocations. - InX::RelaPlt = make<RelocationSection<ELFT>>( + In.RelaPlt = make<RelocationSection<ELFT>>( Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/); - Add(InX::RelaPlt); + Add(In.RelaPlt); // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure // that the IRelative relocations are processed last by the dynamic loader. @@ -387,34 +402,42 @@ template <class ELFT> static void createSyntheticSections() { // packing is enabled because that would cause a section type mismatch. // However, because the Android dynamic loader reads .rel.plt after .rel.dyn, // we can get the desired behaviour by placing the iplt section in .rel.plt. - InX::RelaIplt = make<RelocationSection<ELFT>>( + In.RelaIplt = make<RelocationSection<ELFT>>( (Config->EMachine == EM_ARM && !Config->AndroidPackDynRelocs) ? ".rel.dyn" - : InX::RelaPlt->Name, + : In.RelaPlt->Name, false /*Sort*/); - Add(InX::RelaIplt); - - InX::Plt = make<PltSection>(false); - Add(InX::Plt); - InX::Iplt = make<PltSection>(true); - Add(InX::Iplt); + Add(In.RelaIplt); + + In.Plt = make<PltSection>(false); + Add(In.Plt); + In.Iplt = make<PltSection>(true); + Add(In.Iplt); + + // .note.GNU-stack is always added when we are creating a re-linkable + // object file. Other linkers are using the presence of this marker + // section to control the executable-ness of the stack area, but that + // is irrelevant these days. Stack area should always be non-executable + // by default. So we emit this section unconditionally. + if (Config->Relocatable) + Add(make<GnuStackSection>()); if (!Config->Relocatable) { if (Config->EhFrameHdr) { - InX::EhFrameHdr = make<EhFrameHeader>(); - Add(InX::EhFrameHdr); + In.EhFrameHdr = make<EhFrameHeader>(); + Add(In.EhFrameHdr); } - InX::EhFrame = make<EhFrameSection>(); - Add(InX::EhFrame); + In.EhFrame = make<EhFrameSection>(); + Add(In.EhFrame); } - if (InX::SymTab) - Add(InX::SymTab); - if (InX::SymTabShndx) - Add(InX::SymTabShndx); - Add(InX::ShStrTab); - if (InX::StrTab) - Add(InX::StrTab); + if (In.SymTab) + Add(In.SymTab); + if (In.SymTabShndx) + Add(In.SymTabShndx); + Add(In.ShStrTab); + if (In.StrTab) + Add(In.StrTab); if (Config->EMachine == EM_ARM && !Config->Relocatable) // Add a sentinel to terminate .ARM.exidx. It helps an unwinder @@ -451,6 +474,7 @@ template <class ELFT> void Writer<ELFT>::run() { // to the string table, and add entries to .got and .plt. // finalizeSections does that. finalizeSections(); + checkExecuteOnly(); if (errorCount()) return; @@ -476,10 +500,9 @@ template <class ELFT> void Writer<ELFT>::run() { setPhdrs(); - if (Config->Relocatable) { + if (Config->Relocatable) for (OutputSection *Sec : OutputSections) Sec->Addr = 0; - } if (Config->CheckSections) checkSections(); @@ -548,9 +571,11 @@ static bool includeInSymtab(const Symbol &B) { if (!Sec) return true; Sec = Sec->Repl; + // Exclude symbols pointing to garbage-collected sections. if (isa<InputSectionBase>(Sec) && !Sec->Live) return false; + if (auto *S = dyn_cast<MergeInputSection>(Sec)) if (!S->getSectionPiece(D->Value)->Live) return false; @@ -562,7 +587,7 @@ static bool includeInSymtab(const Symbol &B) { // 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() { - if (!InX::SymTab) + if (!In.SymTab) return; for (InputFile *File : ObjectFiles) { ObjFile<ELFT> *F = cast<ObjFile<ELFT>>(File); @@ -581,16 +606,16 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { SectionBase *Sec = DR->Section; if (!shouldKeepInSymtab(Sec, B->getName(), *B)) continue; - InX::SymTab->addSymbol(B); + In.SymTab->addSymbol(B); } } } +// Create a section symbol for each output section so that we can represent +// relocations that point to the section. If we know that no relocation is +// referring to a section (that happens if the section is a synthetic one), we +// don't create a section symbol for that section. template <class ELFT> void Writer<ELFT>::addSectionSymbols() { - // Create a section symbol for each output section so that we can represent - // relocations that point to the section. If we know that no relocation is - // referring to a section (that happens if the section is a synthetic one), we - // don't create a section symbol for that section. for (BaseCommand *Base : Script->SectionCommands) { auto *Sec = dyn_cast<OutputSection>(Base); if (!Sec) @@ -617,7 +642,7 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() { auto *Sym = make<Defined>(IS->File, "", STB_LOCAL, /*StOther=*/0, STT_SECTION, /*Value=*/0, /*Size=*/0, IS); - InX::SymTab->addSymbol(Sym); + In.SymTab->addSymbol(Sym); } } @@ -662,9 +687,14 @@ static bool isRelroSection(const OutputSection *Sec) { // .got contains pointers to external symbols. They are resolved by // the dynamic linker when a module is loaded into memory, and after // that they are not expected to change. So, it can be in RELRO. - if (InX::Got && Sec == InX::Got->getParent()) + if (In.Got && Sec == In.Got->getParent()) return true; + // .toc is a GOT-ish section for PowerPC64. Their contents are accessed + // through r2 register, which is reserved for that purpose. Since r2 is used + // for accessing .got as well, .got and .toc need to be close enough in the + // virtual address space. Usually, .toc comes just after .got. Since we place + // .got into RELRO, .toc needs to be placed into RELRO too. if (Sec->Name.equals(".toc")) return true; @@ -672,13 +702,13 @@ static bool isRelroSection(const OutputSection *Sec) { // by default resolved lazily, so we usually cannot put it into RELRO. // However, if "-z now" is given, the lazy symbol resolution is // disabled, which enables us to put it into RELRO. - if (Sec == InX::GotPlt->getParent()) + if (Sec == In.GotPlt->getParent()) return Config->ZNow; // .dynamic section contains data for the dynamic linker, and // there's no need to write to it at runtime, so it's better to put // it into RELRO. - if (Sec == InX::Dynamic->getParent()) + if (Sec == In.Dynamic->getParent()) return true; // Sections with some special names are put into RELRO. This is a @@ -700,17 +730,17 @@ static bool isRelroSection(const OutputSection *Sec) { // * It is easy two see how similar two ranks are (see getRankProximity). enum RankFlags { RF_NOT_ADDR_SET = 1 << 18, - RF_NOT_INTERP = 1 << 17, - RF_NOT_ALLOC = 1 << 16, - RF_WRITE = 1 << 15, - RF_EXEC_WRITE = 1 << 14, - RF_EXEC = 1 << 13, - RF_RODATA = 1 << 12, - RF_NON_TLS_BSS = 1 << 11, - RF_NON_TLS_BSS_RO = 1 << 10, - RF_NOT_TLS = 1 << 9, - RF_BSS = 1 << 8, - RF_NOTE = 1 << 7, + RF_NOT_ALLOC = 1 << 17, + RF_NOT_INTERP = 1 << 16, + RF_NOT_NOTE = 1 << 15, + RF_WRITE = 1 << 14, + RF_EXEC_WRITE = 1 << 13, + RF_EXEC = 1 << 12, + RF_RODATA = 1 << 11, + RF_NON_TLS_BSS = 1 << 10, + RF_NON_TLS_BSS_RO = 1 << 9, + RF_NOT_TLS = 1 << 8, + RF_BSS = 1 << 7, RF_PPC_NOT_TOCBSS = 1 << 6, RF_PPC_TOCL = 1 << 5, RF_PPC_TOC = 1 << 4, @@ -729,16 +759,24 @@ static unsigned getSectionRank(const OutputSection *Sec) { return Rank; Rank |= RF_NOT_ADDR_SET; + // Allocatable sections go first to reduce the total PT_LOAD size and + // so debug info doesn't change addresses in actual code. + if (!(Sec->Flags & SHF_ALLOC)) + return Rank | RF_NOT_ALLOC; + // Put .interp first because some loaders want to see that section // on the first page of the executable file when loaded into memory. if (Sec->Name == ".interp") return Rank; Rank |= RF_NOT_INTERP; - // Allocatable sections go first to reduce the total PT_LOAD size and - // so debug info doesn't change addresses in actual code. - if (!(Sec->Flags & SHF_ALLOC)) - return Rank | RF_NOT_ALLOC; + // Put .note sections (which make up one PT_NOTE) at the beginning so that + // they are likely to be included in a core file even if core file size is + // limited. In particular, we want a .note.gnu.build-id and a .note.tag to be + // included in a core to match core files with executables. + if (Sec->Type == SHT_NOTE) + return Rank; + Rank |= RF_NOT_NOTE; // Sort sections based on their access permission in the following // order: R, RX, RWX, RW. This order is based on the following @@ -802,12 +840,6 @@ static unsigned getSectionRank(const OutputSection *Sec) { if (IsNoBits) Rank |= RF_BSS; - // We create a NOTE segment for contiguous .note sections, so make - // them contigous if there are more than one .note section with the - // same attributes. - if (Sec->Type == SHT_NOTE) - Rank |= RF_NOTE; - // Some architectures have additional ordering restrictions for sections // within the same PT_LOAD. if (Config->EMachine == EM_PPC64) { @@ -850,8 +882,10 @@ static unsigned getSectionRank(const OutputSection *Sec) { static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { const OutputSection *A = cast<OutputSection>(ACmd); const OutputSection *B = cast<OutputSection>(BCmd); + if (A->SortRank != B->SortRank) return A->SortRank < B->SortRank; + if (!(A->SortRank & RF_NOT_ADDR_SET)) return Config->SectionStartMap.lookup(A->Name) < Config->SectionStartMap.lookup(B->Name); @@ -874,14 +908,20 @@ void PhdrEntry::add(OutputSection *Sec) { // 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() { - if (needsInterpSection()) + if (Config->Relocatable || needsInterpSection()) return; - StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); - S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; - ElfSym::RelaIpltEnd = - addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); + // By default, __rela_iplt_{start,end} belong to a dummy section 0 + // because .rela.plt might be empty and thus removed from output. + // We'll override Out::ElfHeader with In.RelaIplt later when we are + // sure that .rela.plt exists in output. + ElfSym::RelaIpltStart = addOptionalRegular( + Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start", + Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK); + + ElfSym::RelaIpltEnd = addOptionalRegular( + Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end", + Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK); } template <class ELFT> @@ -895,7 +935,7 @@ void Writer<ELFT>::forEachRelSec( for (InputSectionBase *IS : InputSections) if (IS->Live && isa<InputSection>(IS) && (IS->Flags & SHF_ALLOC)) Fn(*IS); - for (EhInputSection *ES : InX::EhFrame->Sections) + for (EhInputSection *ES : In.EhFrame->Sections) Fn(*ES); } @@ -908,15 +948,19 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { if (ElfSym::GlobalOffsetTable) { // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually // to the start of the .got or .got.plt section. - InputSection *GotSection = InX::GotPlt; + InputSection *GotSection = In.GotPlt; if (!Target->GotBaseSymInGotPlt) - GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot) - : cast<InputSection>(InX::Got); + GotSection = In.MipsGot ? cast<InputSection>(In.MipsGot) + : cast<InputSection>(In.Got); ElfSym::GlobalOffsetTable->Section = GotSection; } - if (ElfSym::RelaIpltEnd) - ElfSym::RelaIpltEnd->Value = InX::RelaIplt->getSize(); + // .rela_iplt_{start,end} mark the start and the end of .rela.plt section. + if (ElfSym::RelaIpltStart && !In.RelaIplt->empty()) { + ElfSym::RelaIpltStart->Section = In.RelaIplt; + ElfSym::RelaIpltEnd->Section = In.RelaIplt; + ElfSym::RelaIpltEnd->Value = In.RelaIplt->getSize(); + } PhdrEntry *Last = nullptr; PhdrEntry *LastRO = nullptr; @@ -1088,7 +1132,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() { SymbolOrderEntry &Ent = It->second; Ent.Present = true; - warnUnorderableSymbol(&Sym); + maybeWarnUnorderableSymbol(&Sym); if (auto *D = dyn_cast<Defined>(&Sym)) { if (auto *Sec = dyn_cast_or_null<InputSectionBase>(D->Section)) { @@ -1097,6 +1141,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() { } } }; + // We want both global and local symbols. We get the global ones from the // symbol table and iterate the object files for the local ones. for (Symbol *Sym : Symtab->getSymbols()) @@ -1132,11 +1177,10 @@ sortISDBySectionOrder(InputSectionDescription *ISD, } OrderedSections.push_back({IS, I->second}); } - llvm::sort( - OrderedSections.begin(), OrderedSections.end(), - [&](std::pair<InputSection *, int> A, std::pair<InputSection *, int> B) { - return A.second < B.second; - }); + llvm::sort(OrderedSections, [&](std::pair<InputSection *, int> A, + std::pair<InputSection *, int> B) { + return A.second < B.second; + }); // Find an insertion point for the ordered section list in the unordered // section list. On targets with limited-range branches, this is the mid-point @@ -1166,7 +1210,7 @@ sortISDBySectionOrder(InputSectionDescription *ISD, // we effectively double the amount of code that could potentially call into // the hot code without a thunk. size_t InsPt = 0; - if (Target->ThunkSectionSpacing && !OrderedSections.empty()) { + if (Target->getThunkSectionSpacing() && !OrderedSections.empty()) { uint64_t UnorderedPos = 0; for (; InsPt != UnorderedSections.size(); ++InsPt) { UnorderedPos += UnorderedSections[InsPt]->getSize(); @@ -1342,10 +1386,12 @@ static bool compareByFilePosition(InputSection *A, InputSection *B) { if (A->kind() == InputSectionBase::Synthetic || B->kind() == InputSectionBase::Synthetic) return A->kind() != InputSectionBase::Synthetic; + InputSection *LA = A->getLinkOrderDep(); InputSection *LB = B->getLinkOrderDep(); OutputSection *AOut = LA->getParent(); OutputSection *BOut = LB->getParent(); + if (AOut != BOut) return AOut->SectionIndex < BOut->SectionIndex; return LA->OutSecOff < LB->OutSecOff; @@ -1392,6 +1438,7 @@ static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) { for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>()) if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind) return false; + // All table entries in this .ARM.exidx Section can be merged into the // previous Section. return true; @@ -1423,18 +1470,19 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { assert(Sections.size() >= 2 && "We should create a sentinel section only if there are " "alive regular exidx sections."); + // The last executable section is required to fill the sentinel. // Remember it here so that we don't have to find it again. Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep(); } + // The EHABI for the Arm Architecture permits consecutive identical + // table entries to be merged. We use a simple implementation that + // removes a .ARM.exidx Input Section if it can be merged into the + // previous one. This does not require any rewriting of InputSection + // contents but misses opportunities for fine grained deduplication + // where only a subset of the InputSection contents can be merged. if (Config->MergeArmExidx) { - // The EHABI for the Arm Architecture permits consecutive identical - // table entries to be merged. We use a simple implementation that - // removes a .ARM.exidx Input Section if it can be merged into the - // previous one. This does not require any rewriting of InputSection - // contents but misses opportunities for fine grained deduplication - // where only a subset of the InputSection contents can be merged. size_t Prev = 0; // The last one is a sentinel entry which should not be removed. for (size_t I = 1; I < Sections.size() - 1; ++I) { @@ -1456,11 +1504,49 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { } } -static void applySynthetic(const std::vector<SyntheticSection *> &Sections, - llvm::function_ref<void(SyntheticSection *)> Fn) { - for (SyntheticSection *SS : Sections) - if (SS && SS->getParent() && !SS->empty()) - Fn(SS); +// For most RISC ISAs, we need to generate content that depends on the address +// of InputSections. For example some architectures such as AArch64 use small +// displacements for jump instructions that is the linker's responsibility for +// creating range extension thunks for. As the generation of the content may +// also alter InputSection addresses we must converge to a fixed point. +template <class ELFT> void Writer<ELFT>::maybeAddThunks() { + if (!Target->NeedsThunks && !Config->AndroidPackDynRelocs && + !Config->RelrPackDynRelocs) + return; + + ThunkCreator TC; + AArch64Err843419Patcher A64P; + + for (;;) { + bool Changed = false; + + Script->assignAddresses(); + + if (Target->NeedsThunks) + Changed |= TC.createThunks(OutputSections); + + if (Config->FixCortexA53Errata843419) { + if (Changed) + Script->assignAddresses(); + Changed |= A64P.createFixes(); + } + + if (In.MipsGot) + In.MipsGot->updateAllocSize(); + + Changed |= In.RelaDyn->updateAllocSize(); + + if (In.RelrDyn) + Changed |= In.RelrDyn->updateAllocSize(); + + if (!Changed) + return; + } +} + +static void finalizeSynthetic(SyntheticSection *Sec) { + if (Sec && !Sec->empty() && Sec->getParent()) + Sec->finalizeContents(); } // In order to allow users to manipulate linker-synthesized sections, @@ -1500,6 +1586,7 @@ static void removeUnusedSyntheticSections() { // with the same name defined in other ELF executable or DSO. static bool computeIsPreemptible(const Symbol &B) { assert(!B.isLocal()); + // Only symbols that appear in dynsym can be preempted. if (!B.includeInDynsym()) return false; @@ -1528,7 +1615,6 @@ static bool computeIsPreemptible(const Symbol &B) { // Create output section objects and add them to OutputSections. template <class ELFT> void Writer<ELFT>::finalizeSections() { - Out::DebugInfo = findSection(".debug_info"); Out::PreinitArray = findSection(".preinit_array"); Out::InitArray = findSection(".init_array"); Out::FiniArray = findSection(".fini_array"); @@ -1547,46 +1633,51 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // 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 (InX::DynSymTab) - Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, - /*Size=*/0, STB_WEAK, InX::Dynamic, + if (In.Dynamic->Parent) + Symtab->addDefined("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, + /*Size=*/0, STB_WEAK, In.Dynamic, /*File=*/nullptr); // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); + // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined. + if (Config->EMachine == EM_RISCV) + if (!dyn_cast_or_null<Defined>(Symtab->find("__global_pointer$"))) + addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800); + // This responsible for splitting up .eh_frame section into // pieces. The relocation scan uses those pieces, so this has to be // earlier. - applySynthetic({InX::EhFrame}, - [](SyntheticSection *SS) { SS->finalizeContents(); }); + finalizeSynthetic(In.EhFrame); for (Symbol *S : Symtab->getSymbols()) - S->IsPreemptible |= computeIsPreemptible(*S); + if (!S->IsPreemptible) + S->IsPreemptible = computeIsPreemptible(*S); // Scan relocations. This must be done after every symbol is declared so that // we can correctly decide if a dynamic relocation is needed. if (!Config->Relocatable) forEachRelSec(scanRelocations<ELFT>); - if (InX::Plt && !InX::Plt->empty()) - InX::Plt->addSymbols(); - if (InX::Iplt && !InX::Iplt->empty()) - InX::Iplt->addSymbols(); + if (In.Plt && !In.Plt->empty()) + In.Plt->addSymbols(); + if (In.Iplt && !In.Iplt->empty()) + In.Iplt->addSymbols(); // Now that we have defined all possible global symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. for (Symbol *Sym : Symtab->getSymbols()) { if (!includeInSymtab(*Sym)) continue; - if (InX::SymTab) - InX::SymTab->addSymbol(Sym); + if (In.SymTab) + In.SymTab->addSymbol(Sym); - if (InX::DynSymTab && Sym->includeInDynsym()) { - InX::DynSymTab->addSymbol(Sym); + if (Sym->includeInDynsym()) { + In.DynSymTab->addSymbol(Sym); if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File)) if (File->IsNeeded && !Sym->isUndefined()) - In<ELFT>::VerNeed->addSymbol(Sym); + InX<ELFT>::VerNeed->addSymbol(Sym); } } @@ -1594,8 +1685,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (errorCount()) return; - if (InX::MipsGot) - InX::MipsGot->build<ELFT>(); + if (In.MipsGot) + In.MipsGot->build<ELFT>(); removeUnusedSyntheticSections(); @@ -1607,15 +1698,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (auto *Sec = dyn_cast<OutputSection>(Base)) OutputSections.push_back(Sec); - // Ensure data sections are not mixed with executable sections when - // -execute-only is used. - if (Config->ExecuteOnly) - for (OutputSection *OS : OutputSections) - if (OS->Flags & SHF_EXECINSTR) - for (InputSection *IS : getInputSections(OS)) - if (!(IS->Flags & SHF_EXECINSTR)) - error("-execute-only does not support intermingling data and code"); - // Prefer command line supplied address over other constraints. for (OutputSection *Sec : OutputSections) { auto I = Config->SectionStartMap.find(Sec->Name); @@ -1628,10 +1710,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // particularly relevant. Out::ElfHeader->SectionIndex = 1; - unsigned I = 1; - for (OutputSection *Sec : OutputSections) { - Sec->SectionIndex = I++; - Sec->ShName = InX::ShStrTab->addString(Sec->Name); + for (size_t I = 0, E = OutputSections.size(); I != E; ++I) { + OutputSection *Sec = OutputSections[I]; + Sec->SectionIndex = I + 1; + Sec->ShName = In.ShStrTab->addString(Sec->Name); } // Binary and relocatable output does not have PHDRS. @@ -1641,6 +1723,12 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs(); addPtArmExid(Phdrs); Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); + + // Find the TLS segment. This happens before the section layout loop so that + // Android relocation packing can look up TLS symbol addresses. + for (PhdrEntry *P : Phdrs) + if (P->p_type == PT_TLS) + Out::TlsPhdr = P; } // Some symbols are defined in term of program headers. Now that we @@ -1649,15 +1737,30 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. - applySynthetic( - {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab, - InX::HashTab, InX::SymTab, InX::SymTabShndx, InX::ShStrTab, - InX::StrTab, In<ELFT>::VerDef, InX::DynStrTab, InX::Got, - InX::MipsGot, InX::IgotPlt, InX::GotPlt, InX::RelaDyn, - InX::RelrDyn, InX::RelaIplt, InX::RelaPlt, InX::Plt, - InX::Iplt, InX::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed, - InX::Dynamic}, - [](SyntheticSection *SS) { SS->finalizeContents(); }); + finalizeSynthetic(In.DynSymTab); + finalizeSynthetic(In.Bss); + finalizeSynthetic(In.BssRelRo); + finalizeSynthetic(In.GnuHashTab); + finalizeSynthetic(In.HashTab); + finalizeSynthetic(In.SymTabShndx); + finalizeSynthetic(In.ShStrTab); + finalizeSynthetic(In.StrTab); + finalizeSynthetic(In.VerDef); + finalizeSynthetic(In.DynStrTab); + finalizeSynthetic(In.Got); + finalizeSynthetic(In.MipsGot); + finalizeSynthetic(In.IgotPlt); + finalizeSynthetic(In.GotPlt); + finalizeSynthetic(In.RelaDyn); + finalizeSynthetic(In.RelrDyn); + finalizeSynthetic(In.RelaIplt); + finalizeSynthetic(In.RelaPlt); + finalizeSynthetic(In.Plt); + finalizeSynthetic(In.Iplt); + finalizeSynthetic(In.EhFrameHdr); + finalizeSynthetic(InX<ELFT>::VerSym); + finalizeSynthetic(InX<ELFT>::VerNeed); + finalizeSynthetic(In.Dynamic); if (!Script->HasSectionsCommand && !Config->Relocatable) fixSectionAlignments(); @@ -1666,37 +1769,21 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { // needs to be resolved before any other address dependent operation. resolveShfLinkOrder(); - // Some architectures need to generate content that depends on the address - // of InputSections. For example some architectures use small displacements - // for jump instructions that is the linker's responsibility for creating - // range extension thunks for. As the generation of the content may also - // alter InputSection addresses we must converge to a fixed point. - if (Target->NeedsThunks || Config->AndroidPackDynRelocs || - Config->RelrPackDynRelocs) { - ThunkCreator TC; - AArch64Err843419Patcher A64P; - bool Changed; - do { - Script->assignAddresses(); - Changed = false; - if (Target->NeedsThunks) - Changed |= TC.createThunks(OutputSections); - if (Config->FixCortexA53Errata843419) { - if (Changed) - Script->assignAddresses(); - Changed |= A64P.createFixes(); - } - if (InX::MipsGot) - InX::MipsGot->updateAllocSize(); - Changed |= InX::RelaDyn->updateAllocSize(); - if (InX::RelrDyn) - Changed |= InX::RelrDyn->updateAllocSize(); - } while (Changed); - } + // Jump instructions in many ISAs have small displacements, and therefore they + // cannot jump to arbitrary addresses in memory. For example, RISC-V JAL + // instruction can target only +-1 MiB from PC. It is a linker's + // responsibility to create and insert small pieces of code between sections + // to extend the ranges if jump targets are out of range. Such code pieces are + // called "thunks". + // + // We add thunks at this stage. We couldn't do this before this point because + // this is the earliest point where we know sizes of sections and their + // layouts (that are needed to determine if jump targets are in range). + maybeAddThunks(); - // createThunks may have added local symbols to the static symbol table - applySynthetic({InX::SymTab}, - [](SyntheticSection *SS) { SS->postThunkContents(); }); + // maybeAddThunks may have added local symbols to the static symbol table. + finalizeSynthetic(In.SymTab); + finalizeSynthetic(In.PPC64LongBranchTarget); // Fill other section headers. The dynamic table is finalized // at the end because some tags like RELSZ depend on result @@ -1705,6 +1792,21 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { Sec->finalize<ELFT>(); } +// Ensure data sections are not mixed with executable sections when +// -execute-only is used. -execute-only is a feature to make pages executable +// but not readable, and the feature is currently supported only on AArch64. +template <class ELFT> void Writer<ELFT>::checkExecuteOnly() { + if (!Config->ExecuteOnly) + return; + + for (OutputSection *OS : OutputSections) + if (OS->Flags & SHF_EXECINSTR) + for (InputSection *IS : getInputSections(OS)) + if (!(IS->Flags & SHF_EXECINSTR)) + error("cannot place " + toString(IS) + " into " + toString(OS->Name) + + ": -execute-only does not support intermingling data and code"); +} + // The linker is expected to define SECNAME_start and SECNAME_end // symbols for a few sections. This function defines them. template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { @@ -1721,9 +1823,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { // program to fail to link due to relocation overflow, if their // program text is above 2 GiB. We use the address of the .text // section instead to prevent that failure. + // + // In a rare sitaution, .text section may not exist. If that's the + // case, use the image base address as a last resort. OutputSection *Default = findSection(".text"); if (!Default) Default = Out::ElfHeader; + auto Define = [=](StringRef Start, StringRef End, OutputSection *OS) { if (OS) { addOptionalRegular(Start, OS, 0); @@ -1763,7 +1869,7 @@ static bool needsPtLoad(OutputSection *Sec) { // 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->Flags & SHF_TLS && Sec->Type == SHT_NOBITS) + if ((Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS) return false; return true; } @@ -1815,12 +1921,14 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { // Segments are contiguous memory regions that has the same attributes // (e.g. executable or writable). There is one phdr for each segment. // Therefore, we need to create a new phdr when the next section has - // different flags or is loaded at a discontiguous address using AT linker - // script command. At the same time, we don't want to create a separate - // load segment for the headers, even if the first output section has - // an AT attribute. + // different flags or is loaded at a discontiguous address or memory + // region using AT or AT> linker script command, respectively. At the same + // time, we don't want to create a separate load segment for the headers, + // even if the first output section has an AT or AT> attribute. uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); - if ((Sec->LMAExpr && Load->LastSec != Out::ProgramHeaders) || + if (((Sec->LMAExpr || + (Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) && + Load->LastSec != Out::ProgramHeaders) || Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) { Load = AddHdr(PT_LOAD, NewFlags); @@ -1839,9 +1947,8 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { Ret.push_back(TlsHdr); // Add an entry for .dynamic. - if (InX::DynSymTab) - AddHdr(PT_DYNAMIC, InX::Dynamic->getParent()->getPhdrFlags()) - ->add(InX::Dynamic->getParent()); + if (OutputSection *Sec = In.Dynamic->getParent()) + AddHdr(PT_DYNAMIC, Sec->getPhdrFlags())->add(Sec); // PT_GNU_RELRO includes all sections that should be marked as // read-only by dynamic linker after proccessing relocations. @@ -1869,10 +1976,10 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { Ret.push_back(RelRo); // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. - if (!InX::EhFrame->empty() && InX::EhFrameHdr && InX::EhFrame->getParent() && - InX::EhFrameHdr->getParent()) - AddHdr(PT_GNU_EH_FRAME, InX::EhFrameHdr->getParent()->getPhdrFlags()) - ->add(InX::EhFrameHdr->getParent()); + if (!In.EhFrame->empty() && In.EhFrameHdr && In.EhFrame->getParent() && + In.EhFrameHdr->getParent()) + AddHdr(PT_GNU_EH_FRAME, In.EhFrameHdr->getParent()->getPhdrFlags()) + ->add(In.EhFrameHdr->getParent()); // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes // the dynamic linker fill the segment with random data. @@ -1943,77 +2050,77 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { for (const PhdrEntry *P : Phdrs) { if (P->p_type != PT_GNU_RELRO) continue; + if (P->FirstSec) PageAlign(P->FirstSec); + // 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->LastSec); if (I == End || (I + 1) == End) continue; + OutputSection *Cmd = (*(I + 1)); if (needsPtLoad(Cmd)) PageAlign(Cmd); } } -// 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. -static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) { - OutputSection *First = Cmd->PtLoad ? Cmd->PtLoad->FirstSec : nullptr; - // The first section in a PT_LOAD has to have congruent offset and address - // module the page size. - if (Cmd == First) - return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize), - Cmd->Addr); - - // For SHT_NOBITS we don't want the alignment of the section to impact the - // offset of the sections that follow. Since nothing seems to care about the - // sh_offset of the SHT_NOBITS section itself, just ignore it. - if (Cmd->Type == SHT_NOBITS) +// Compute an in-file position for a given section. 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. +static uint64_t computeFileOffset(OutputSection *OS, uint64_t Off) { + // File offsets are not significant for .bss sections. By convention, we keep + // section offsets monotonically increasing rather than setting to zero. + if (OS->Type == SHT_NOBITS) return Off; // If the section is not in a PT_LOAD, we just have to align it. - if (!Cmd->PtLoad) - return alignTo(Off, Cmd->Alignment); + if (!OS->PtLoad) + return alignTo(Off, OS->Alignment); + + // The first section in a PT_LOAD has to have congruent offset and address + // module the page size. + OutputSection *First = OS->PtLoad->FirstSec; + if (OS == First) { + uint64_t Alignment = std::max<uint64_t>(OS->Alignment, Config->MaxPageSize); + return alignTo(Off, Alignment, OS->Addr); + } // If two sections share the same PT_LOAD the file offset is calculated // using this formula: Off2 = Off1 + (VA2 - VA1). - return First->Offset + Cmd->Addr - First->Addr; + return First->Offset + OS->Addr - First->Addr; } -static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) { - Off = getFileAlignment(Off, Cmd); - Cmd->Offset = Off; +// Set an in-file position to a given section and returns the end position of +// the section. +static uint64_t setFileOffset(OutputSection *OS, uint64_t Off) { + Off = computeFileOffset(OS, Off); + OS->Offset = Off; - // For SHT_NOBITS we should not count the size. - if (Cmd->Type == SHT_NOBITS) + if (OS->Type == SHT_NOBITS) return Off; - - return Off + Cmd->Size; + return Off + OS->Size; } template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { uint64_t Off = 0; for (OutputSection *Sec : OutputSections) if (Sec->Flags & SHF_ALLOC) - Off = setOffset(Sec, Off); + Off = setFileOffset(Sec, Off); FileSize = alignTo(Off, Config->Wordsize); } static std::string rangeToString(uint64_t Addr, uint64_t Len) { - if (Len == 0) - return "<empty range at 0x" + utohexstr(Addr) + ">"; return "[0x" + utohexstr(Addr) + ", 0x" + utohexstr(Addr + Len - 1) + "]"; } // Assign file offsets to output sections. template <class ELFT> void Writer<ELFT>::assignFileOffsets() { uint64_t Off = 0; - Off = setOffset(Out::ElfHeader, Off); - Off = setOffset(Out::ProgramHeaders, Off); + Off = setFileOffset(Out::ElfHeader, Off); + Off = setFileOffset(Out::ProgramHeaders, Off); PhdrEntry *LastRX = nullptr; for (PhdrEntry *P : Phdrs) @@ -2021,9 +2128,10 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { LastRX = P; for (OutputSection *Sec : OutputSections) { - Off = setOffset(Sec, Off); + Off = setFileOffset(Sec, Off); if (Script->HasSectionsCommand) continue; + // If this is a last section of the last executable segment and that // segment is the last loadable segment, align the offset of the // following section to avoid loading non-segments parts of the file. @@ -2048,7 +2156,7 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { continue; if ((Sec->Offset > FileSize) || (Sec->Offset + Sec->Size > FileSize)) error("unable to place section " + Sec->Name + " at file offset " + - rangeToString(Sec->Offset, Sec->Offset + Sec->Size) + + rangeToString(Sec->Offset, Sec->Size) + "; check your linker script for overflows"); } } @@ -2059,19 +2167,23 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() { for (PhdrEntry *P : Phdrs) { OutputSection *First = P->FirstSec; OutputSection *Last = P->LastSec; + if (First) { P->p_filesz = Last->Offset - First->Offset; if (Last->Type != SHT_NOBITS) P->p_filesz += Last->Size; + P->p_memsz = Last->Addr + Last->Size - First->Addr; P->p_offset = First->Offset; P->p_vaddr = First->Addr; + if (!P->HasLMA) P->p_paddr = First->getLMA(); } - if (P->p_type == PT_LOAD) + + if (P->p_type == PT_LOAD) { P->p_align = std::max<uint64_t>(P->p_align, Config->MaxPageSize); - else if (P->p_type == PT_GNU_RELRO) { + } else if (P->p_type == PT_GNU_RELRO) { P->p_align = 1; // The glibc dynamic loader rounds the size down, so we need to round up // to protect the last page. This is a no-op on FreeBSD which always @@ -2079,12 +2191,22 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() { P->p_memsz = alignTo(P->p_memsz, Target->PageSize); } - // 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 (P->p_type == PT_TLS) { - Out::TlsPhdr = P; - if (P->p_memsz) - P->p_memsz = alignTo(P->p_memsz, P->p_align); + if (P->p_type == PT_TLS && P->p_memsz) { + if (!Config->Shared && + (Config->EMachine == EM_ARM || Config->EMachine == EM_AARCH64)) { + // On ARM/AArch64, reserve extra space (8 words) between the thread + // pointer and an executable's TLS segment by overaligning the segment. + // This reservation is needed for backwards compatibility with Android's + // TCB, which allocates several slots after the thread pointer (e.g. + // TLS_SLOT_STACK_GUARD==5). For simplicity, this overalignment is also + // done on other operating systems. + P->p_align = std::max<uint64_t>(P->p_align, Config->Wordsize * 8); + } + + // The TLS pointer goes after PT_TLS for variant 2 targets. At least glibc + // will align it, so round up the size to make sure the offsets are + // correct. + P->p_memsz = alignTo(P->p_memsz, P->p_align); } } } @@ -2101,10 +2223,9 @@ struct SectionOffset { // load and virtual adresses). static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections, bool IsVirtualAddr) { - llvm::sort(Sections.begin(), Sections.end(), - [=](const SectionOffset &A, const SectionOffset &B) { - return A.Offset < B.Offset; - }); + llvm::sort(Sections, [=](const SectionOffset &A, const SectionOffset &B) { + return A.Offset < B.Offset; + }); // Finding overlap is easy given a vector is sorted by start position. // If an element starts before the end of the previous element, they overlap. @@ -2148,7 +2269,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { // file so we skip any non-allocated sections in that case. std::vector<SectionOffset> FileOffs; for (OutputSection *Sec : OutputSections) - if (0 < Sec->Size && Sec->Type != SHT_NOBITS && + if (Sec->Size > 0 && Sec->Type != SHT_NOBITS && (!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC))) FileOffs.push_back({Sec, Sec->Offset}); checkOverlap("file", FileOffs, false); @@ -2166,7 +2287,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { // ranges in the file. std::vector<SectionOffset> VMAs; for (OutputSection *Sec : OutputSections) - if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) + if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) VMAs.push_back({Sec, Sec->Addr}); checkOverlap("virtual address", VMAs, true); @@ -2175,7 +2296,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { // script with AT(). std::vector<SectionOffset> LMAs; for (OutputSection *Sec : OutputSections) - if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) + if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) LMAs.push_back({Sec, Sec->getLMA()}); checkOverlap("load address", LMAs, false); } @@ -2188,7 +2309,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { // 4. the number represented by the entry symbol, if it is a number; // 5. the address of the first byte of the .text section, if present; // 6. the address 0. -template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() { +static uint64_t getEntryAddr() { // Case 1, 2 or 3 if (Symbol *B = Symtab->find(Config->Entry)) return B->getVA(); @@ -2231,6 +2352,7 @@ static uint8_t getAbiVersion() { template <class ELFT> void Writer<ELFT>::writeHeader() { uint8_t *Buf = Buffer->getBufferStart(); + // For executable segments, the trap instructions are written before writing // the header. Setting Elf header bytes to zero ensures that any unused bytes // in header are zero-cleared, instead of having trap instructions. @@ -2289,7 +2411,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { else EHdr->e_shnum = Num; - uint32_t StrTabIndex = InX::ShStrTab->getParent()->SectionIndex; + uint32_t StrTabIndex = In.ShStrTab->getParent()->SectionIndex; if (StrTabIndex >= SHN_LORESERVE) { SHdrs->sh_link = StrTabIndex; EHdr->e_shstrndx = SHN_XINDEX; @@ -2303,7 +2425,8 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { // Open a result file. template <class ELFT> void Writer<ELFT>::openFile() { - if (!Config->Is64 && FileSize > UINT32_MAX) { + uint64_t MaxSize = Config->Is64 ? INT64_MAX : UINT32_MAX; + if (MaxSize < FileSize) { error("output file too large: " + Twine(FileSize) + " bytes"); return; } @@ -2368,8 +2491,8 @@ template <class ELFT> void Writer<ELFT>::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); OutputSection *EhFrameHdr = nullptr; - if (InX::EhFrameHdr && !InX::EhFrameHdr->empty()) - EhFrameHdr = InX::EhFrameHdr->getParent(); + if (In.EhFrameHdr && !In.EhFrameHdr->empty()) + EhFrameHdr = In.EhFrameHdr->getParent(); // In -r or -emit-relocs mode, write the relocation sections first as in // ELf_Rel targets we might find out that we need to modify the relocated @@ -2389,13 +2512,13 @@ template <class ELFT> void Writer<ELFT>::writeSections() { } template <class ELFT> void Writer<ELFT>::writeBuildId() { - if (!InX::BuildId || !InX::BuildId->getParent()) + if (!In.BuildId || !In.BuildId->getParent()) return; // Compute a hash of all sections of the output file. uint8_t *Start = Buffer->getBufferStart(); uint8_t *End = Start + FileSize; - InX::BuildId->writeBuildId({Start, End}); + In.BuildId->writeBuildId({Start, End}); } template void elf::writeResult<ELF32LE>(); |