diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-08-02 17:33:42 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-08-02 17:33:42 +0000 |
commit | 84c4061b34e048f47e5eb4fbabc1558495e8157c (patch) | |
tree | 83f9a0fbaadd2f5e3adac8f066cc8160781b385d /ELF | |
parent | 20d35e67e67f106f617c939725101223211659f0 (diff) | |
download | src-84c4061b34e048f47e5eb4fbabc1558495e8157c.tar.gz src-84c4061b34e048f47e5eb4fbabc1558495e8157c.zip |
Vendor import of lld trunk r338536:vendor/lld/lld-trunk-r338536vendor/lld/lld-release_70-r338892
Notes
Notes:
svn path=/vendor/lld/dist/; revision=337145
svn path=/vendor/lld/lld-release_70-r338892/; revision=337307; tag=vendor/lld/lld-release_70-r338892
Diffstat (limited to 'ELF')
-rw-r--r-- | ELF/Arch/ARM.cpp | 11 | ||||
-rw-r--r-- | ELF/Arch/Hexagon.cpp | 6 | ||||
-rw-r--r-- | ELF/Config.h | 5 | ||||
-rw-r--r-- | ELF/Driver.cpp | 34 | ||||
-rw-r--r-- | ELF/ICF.cpp | 11 | ||||
-rw-r--r-- | ELF/InputFiles.cpp | 42 | ||||
-rw-r--r-- | ELF/InputSection.cpp | 19 | ||||
-rw-r--r-- | ELF/Options.td | 8 | ||||
-rw-r--r-- | ELF/SyntheticSections.cpp | 77 | ||||
-rw-r--r-- | ELF/SyntheticSections.h | 11 | ||||
-rw-r--r-- | ELF/Writer.cpp | 28 |
11 files changed, 202 insertions, 50 deletions
diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp index d99be9be7c36..acf9a615f20b 100644 --- a/ELF/Arch/ARM.cpp +++ b/ELF/Arch/ARM.cpp @@ -97,10 +97,19 @@ ARM::ARM() { } uint32_t ARM::calcEFlags() const { + // The ABIFloatType is used by loaders to detect the floating point calling + // convention. + uint32_t ABIFloatType = 0; + if (Config->ARMVFPArgs == ARMVFPArgKind::Base || + Config->ARMVFPArgs == ARMVFPArgKind::Default) + ABIFloatType = EF_ARM_ABI_FLOAT_SOFT; + else if (Config->ARMVFPArgs == ARMVFPArgKind::VFP) + ABIFloatType = EF_ARM_ABI_FLOAT_HARD; + // We don't currently use any features incompatible with EF_ARM_EABI_VER5, // but we don't have any firm guarantees of conformance. Linux AArch64 // kernels (as of 2016) require an EABI version to be set. - return EF_ARM_EABI_VER5; + return EF_ARM_EABI_VER5 | ABIFloatType; } RelExpr ARM::getRelExpr(RelType Type, const Symbol &S, diff --git a/ELF/Arch/Hexagon.cpp b/ELF/Arch/Hexagon.cpp index 2d5c23fd5ad6..ff5e862bafa2 100644 --- a/ELF/Arch/Hexagon.cpp +++ b/ELF/Arch/Hexagon.cpp @@ -70,6 +70,12 @@ void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { switch (Type) { case R_HEX_NONE: break; + case R_HEX_12_X: + or32le(Loc, applyMask(0x000007e0, Val)); + break; + case R_HEX_32_6_X: + or32le(Loc, applyMask(0x0fff3fff, Val >> 6)); + break; case R_HEX_B15_PCREL: or32le(Loc, applyMask(0x00df20fe, Val >> 2)); break; diff --git a/ELF/Config.h b/ELF/Config.h index ec804c5296bc..622324c13e2d 100644 --- a/ELF/Config.h +++ b/ELF/Config.h @@ -58,6 +58,9 @@ enum class SortSectionPolicy { Default, None, Alignment, Name, Priority }; // For --target2 enum class Target2Policy { Abs, Rel, GotRel }; +// For tracking ARM Float Argument PCS +enum class ARMVFPArgKind { Default, Base, VFP, ToolChain }; + struct SymbolVersion { llvm::StringRef Name; bool IsExternCpp; @@ -133,6 +136,7 @@ struct Configuration { bool EhFrameHdr; bool EmitRelocs; bool EnableNewDtags; + bool ExecuteOnly; bool ExportDynamic; bool FixCortexA53Errata843419; bool GcSections; @@ -195,6 +199,7 @@ struct Configuration { StripPolicy Strip; UnresolvedPolicy UnresolvedSymbols; Target2Policy Target2; + ARMVFPArgKind ARMVFPArgs = ARMVFPArgKind::Default; BuildIdKind BuildId = BuildIdKind::None; ELFKind EKind = ELFNoneKind; uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index 1fc552f011b6..693dba64ab5a 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -302,6 +302,14 @@ static void checkOptions(opt::InputArgList &Args) { if (Config->Pie) error("-r and -pie may not be used together"); } + + if (Config->ExecuteOnly) { + if (Config->EMachine != EM_AARCH64) + error("-execute-only is only supported on AArch64 targets"); + + if (Config->SingleRoRx && !Script->HasSectionsCommand) + error("-execute-only and -no-rosegment cannot be used together"); + } } static const char *getReproduceOption(opt::InputArgList &Args) { @@ -493,6 +501,8 @@ static bool isOutputFormatBinary(opt::InputArgList &Args) { StringRef S = Arg->getValue(); if (S == "binary") return true; + if (S.startswith("elf")) + return false; error("unknown --oformat value: " + S); } return false; @@ -747,6 +757,8 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->EnableNewDtags = Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); Config->Entry = Args.getLastArgValue(OPT_entry); + Config->ExecuteOnly = + Args.hasFlag(OPT_execute_only, OPT_no_execute_only, false); Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); Config->FilterList = args::getStrings(Args, OPT_filter); @@ -1303,6 +1315,12 @@ static void findKeepUniqueSections(opt::InputArgList &Args) { } } +static const char *LibcallRoutineNames[] = { +#define HANDLE_LIBCALL(code, name) name, +#include "llvm/IR/RuntimeLibcalls.def" +#undef HANDLE_LIBCALL +}; + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { @@ -1369,11 +1387,21 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { for (StringRef S : Config->Undefined) handleUndefined<ELFT>(S); - // If an entry symbol is in a static archive, pull out that file now - // to complete the symbol table. After this, no new names except a - // few linker-synthesized ones will be added to the symbol table. + // If an entry symbol is in a static archive, pull out that file now. handleUndefined<ELFT>(Config->Entry); + // If any of our inputs are bitcode files, the LTO code generator may create + // references to certain library functions that might not be explicit in the + // bitcode file's symbol table. If any of those library functions are defined + // in a bitcode file in an archive member, we need to arrange to use LTO to + // compile those archive members by adding them to the link beforehand. + // + // With this the symbol table should be complete. After this, no new names + // except a few linker-synthesized ones will be added to the symbol table. + if (!BitcodeFiles.empty()) + for (const char *S : LibcallRoutineNames) + handleUndefined<ELFT>(S); + // Return if there were name resolution errors. if (errorCount()) return; diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp index ba413b132658..075938bd16b9 100644 --- a/ELF/ICF.cpp +++ b/ELF/ICF.cpp @@ -80,9 +80,10 @@ #include "SyntheticSections.h" #include "Writer.h" #include "lld/Common/Threads.h" -#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/ELF.h" +#include "llvm/Support/xxhash.h" #include <algorithm> #include <atomic> @@ -155,12 +156,6 @@ private: }; } -// Returns a hash value for S. Note that the information about -// relocation targets is not included in the hash value. -template <class ELFT> static uint32_t getHash(InputSection *S) { - return hash_combine(S->Flags, S->getSize(), S->NumRelocations, S->Data); -} - // Returns true if section S is subject of ICF. static bool isEligible(InputSection *S) { if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC)) @@ -441,7 +436,7 @@ template <class ELFT> void ICF<ELFT>::run() { // Initially, we use hash values to partition sections. parallelForEach(Sections, [&](InputSection *S) { // Set MSB to 1 to avoid collisions with non-hash IDs. - S->Class[0] = getHash<ELFT>(S) | (1U << 31); + S->Class[0] = xxHash64(S->Data) | (1U << 31); }); // From now on, sections in Sections vector are ordered so that sections diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index 6da722f6f30e..0eb605a556ae 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -494,6 +494,46 @@ void ObjFile<ELFT>::initializeSections( } } +// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD +// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how +// the input objects have been compiled. +static void updateARMVFPArgs(const ARMAttributeParser &Attributes, + const InputFile *F) { + if (!Attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args)) + // If an ABI tag isn't present then it is implicitly given the value of 0 + // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files, + // including some in glibc that don't use FP args (and should have value 3) + // don't have the attribute so we do not consider an implicit value of 0 + // as a clash. + return; + + unsigned VFPArgs = Attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args); + ARMVFPArgKind Arg; + switch (VFPArgs) { + case ARMBuildAttrs::BaseAAPCS: + Arg = ARMVFPArgKind::Base; + break; + case ARMBuildAttrs::HardFPAAPCS: + Arg = ARMVFPArgKind::VFP; + break; + case ARMBuildAttrs::ToolChainFPPCS: + // Tool chain specific convention that conforms to neither AAPCS variant. + Arg = ARMVFPArgKind::ToolChain; + break; + case ARMBuildAttrs::CompatibleFPAAPCS: + // Object compatible with all conventions. + return; + default: + error(toString(F) + ": unknown Tag_ABI_VFP_args value: " + Twine(VFPArgs)); + return; + } + // Follow ld.bfd and error if there is a mix of calling conventions. + if (Config->ARMVFPArgs != Arg && Config->ARMVFPArgs != ARMVFPArgKind::Default) + error(toString(F) + ": incompatible Tag_ABI_VFP_args"); + else + Config->ARMVFPArgs = Arg; +} + // The ARM support in lld makes some use of instructions that are not available // on all ARM architectures. Namely: // - Use of BLX instruction for interworking between ARM and Thumb state. @@ -573,6 +613,8 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec)); Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind); updateSupportedARMFeatures(Attributes); + updateARMVFPArgs(Attributes, this); + // FIXME: Retain the first attribute section we see. The eglibc ARM // dynamic loaders require the presence of an attribute section for dlopen // to work. In a full implementation we would merge all attribute sections. diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp index d6e9a19051e0..54fb57cf9888 100644 --- a/ELF/InputSection.cpp +++ b/ELF/InputSection.cpp @@ -221,8 +221,8 @@ template <class ELFT> Defined *InputSectionBase::getEnclosingFunction(uint64_t Offset) { for (Symbol *B : File->getSymbols()) if (Defined *D = dyn_cast<Defined>(B)) - if (D->Section == this && D->Type == STT_FUNC && - D->Value <= Offset && Offset < D->Value + D->Size) + if (D->Section == this && D->Type == STT_FUNC && D->Value <= Offset && + Offset < D->Value + D->Size) return D; return nullptr; } @@ -671,7 +671,7 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, case R_TLSLD_GOT_FROM_END: return InX::Got->getTlsIndexOff() + A - InX::Got->getSize(); case R_TLSLD_GOT: - return InX::Got->getTlsIndexOff() + A; + return InX::Got->getTlsIndexOff() + A; case R_TLSLD_PC: return InX::Got->getTlsIndexVA() + A - P; } @@ -842,8 +842,7 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { // For each function-defining prologue, find any calls to __morestack, // and replace them with calls to __morestack_non_split. static void switchMorestackCallsToMorestackNonSplit( - llvm::DenseSet<Defined *>& Prologues, - std::vector<Relocation *>& MorestackCalls) { + DenseSet<Defined *> &Prologues, std::vector<Relocation *> &MorestackCalls) { // If the target adjusted a function's prologue, all calls to // __morestack inside that function should be switched to @@ -873,9 +872,8 @@ static void switchMorestackCallsToMorestackNonSplit( } } -static bool -enclosingPrologueAdjusted(uint64_t Offset, - const llvm::DenseSet<Defined *> &Prologues) { +static bool enclosingPrologueAdjusted(uint64_t Offset, + const DenseSet<Defined *> &Prologues) { for (Defined *F : Prologues) if (F->Value <= Offset && Offset < F->Value + F->Size) return true; @@ -891,7 +889,7 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf, uint8_t *End) { if (!getFile<ELFT>()->SplitStack) return; - llvm::DenseSet<Defined *> AdjustedPrologues; + DenseSet<Defined *> AdjustedPrologues; std::vector<Relocation *> MorestackCalls; for (Relocation &Rel : Relocations) { @@ -1071,8 +1069,7 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data, bool IsAlloc = Flags & SHF_ALLOC; for (size_t I = 0; I != Size; I += EntSize) - Pieces.emplace_back(I, xxHash64(toStringRef(Data.slice(I, EntSize))), - !IsAlloc); + Pieces.emplace_back(I, xxHash64(Data.slice(I, EntSize)), !IsAlloc); } template <class ELFT> diff --git a/ELF/Options.td b/ELF/Options.td index 73457db8332f..04a4f8ffbe28 100644 --- a/ELF/Options.td +++ b/ELF/Options.td @@ -58,8 +58,8 @@ defm allow_multiple_definition: B<"allow-multiple-definition", "Do not allow multiple definitions (default)">; defm apply_dynamic_relocs: B<"apply-dynamic-relocs", - "Apply dynamic relocations to place", - "Do not apply dynamic relocations to place">; + "Apply link-time values for dynamic relocations", + "Do not apply link-time values for dynamic relocations (default)">; defm as_needed: B<"as-needed", "Only set DT_NEEDED for shared libraries if used", @@ -131,6 +131,10 @@ def error_unresolved_symbols: F<"error-unresolved-symbols">, defm exclude_libs: Eq<"exclude-libs", "Exclude static libraries from automatic export">; +defm execute_only: B<"execute-only", + "Do not mark executable sections readable", + "Mark executable sections readable (default)">; + defm export_dynamic: B<"export-dynamic", "Put symbols in the dynamic symbol table", "Do not put symbols in the dynamic symbol table (default)">; diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp index 38859e1650bf..ae02434572c2 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -335,7 +335,7 @@ void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { switch (Config->BuildId) { case BuildIdKind::Fast: computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) { - write64le(Dest, xxHash64(toStringRef(Arr))); + write64le(Dest, xxHash64(Arr)); }); break; case BuildIdKind::Md5: @@ -1935,6 +1935,23 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec) this->Entsize = sizeof(Elf_Sym); } +static BssSection *getCommonSec(Symbol *Sym) { + if (!Config->DefineCommon) + if (auto *D = dyn_cast<Defined>(Sym)) + return dyn_cast_or_null<BssSection>(D->Section); + return nullptr; +} + +static uint32_t getSymSectionIndex(Symbol *Sym) { + if (getCommonSec(Sym)) + return SHN_COMMON; + if (!isa<Defined>(Sym) || Sym->NeedsPltAddr) + return SHN_UNDEF; + if (const OutputSection *OS = Sym->getOutputSection()) + return OS->SectionIndex >= SHN_LORESERVE ? SHN_XINDEX : OS->SectionIndex; + return SHN_ABS; +} + // Write the internal symbol table contents to the output symbol table. template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { // The first entry is a null entry as per the ELF spec. @@ -1956,22 +1973,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { } ESym->st_name = Ent.StrTabOffset; - - // Set a section index. - BssSection *CommonSec = nullptr; - if (!Config->DefineCommon) - if (auto *D = dyn_cast<Defined>(Sym)) - CommonSec = dyn_cast_or_null<BssSection>(D->Section); - if (CommonSec) - ESym->st_shndx = SHN_COMMON; - else if (Sym->NeedsPltAddr) - ESym->st_shndx = SHN_UNDEF; - else if (const OutputSection *OutSec = Sym->getOutputSection()) - ESym->st_shndx = OutSec->SectionIndex; - else if (isa<Defined>(Sym)) - ESym->st_shndx = SHN_ABS; - else - ESym->st_shndx = SHN_UNDEF; + ESym->st_shndx = getSymSectionIndex(Ent.Sym); // Copy symbol size if it is a defined symbol. st_size is not significant // for undefined symbols, so whether copying it or not is up to us if that's @@ -1986,7 +1988,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { // st_value is usually an address of a symbol, but that has a // special meaining for uninstantiated common symbols (this can // occur if -r is given). - if (CommonSec) + if (BssSection *CommonSec = getCommonSec(Ent.Sym)) ESym->st_value = CommonSec->Alignment; else ESym->st_value = Sym->getVA(); @@ -2026,6 +2028,44 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { } } +SymtabShndxSection::SymtabShndxSection() + : SyntheticSection(0, SHT_SYMTAB_SHNDX, 4, ".symtab_shndxr") { + this->Entsize = 4; +} + +void SymtabShndxSection::writeTo(uint8_t *Buf) { + // We write an array of 32 bit values, where each value has 1:1 association + // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX, + // we need to write actual index, otherwise, we must write SHN_UNDEF(0). + Buf += 4; // Ignore .symtab[0] entry. + for (const SymbolTableEntry &Entry : InX::SymTab->getSymbols()) { + if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX) + write32(Buf, Entry.Sym->getOutputSection()->SectionIndex); + Buf += 4; + } +} + +bool SymtabShndxSection::empty() const { + // SHT_SYMTAB can hold symbols with section indices values up to + // SHN_LORESERVE. If we need more, we want to use extension SHT_SYMTAB_SHNDX + // section. Problem is that we reveal the final section indices a bit too + // late, and we do not know them here. For simplicity, we just always create + // a .symtab_shndxr section when the amount of output sections is huge. + size_t Size = 0; + for (BaseCommand *Base : Script->SectionCommands) + if (isa<OutputSection>(Base)) + ++Size; + return Size < SHN_LORESERVE; +} + +void SymtabShndxSection::finalizeContents() { + getParent()->Link = InX::SymTab->getParent()->SectionIndex; +} + +size_t SymtabShndxSection::getSize() const { + return InX::SymTab->getNumSymbols() * 4; +} + // .hash and .gnu.hash sections contain on-disk hash tables that map // symbol names to their dynamic symbol table indices. Their purpose // is to help the dynamic linker resolve symbols quickly. If ELF files @@ -3025,6 +3065,7 @@ RelocationBaseSection *InX::RelaIplt; StringTableSection *InX::ShStrTab; StringTableSection *InX::StrTab; SymbolTableBaseSection *InX::SymTab; +SymtabShndxSection *InX::SymTabShndx; template GdbIndexSection *GdbIndexSection::create<ELF32LE>(); template GdbIndexSection *GdbIndexSection::create<ELF32BE>(); diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h index 0366c6c3f8c7..a780c6631374 100644 --- a/ELF/SyntheticSections.h +++ b/ELF/SyntheticSections.h @@ -588,6 +588,16 @@ public: void writeTo(uint8_t *Buf) override; }; +class SymtabShndxSection final : public SyntheticSection { +public: + SymtabShndxSection(); + + void writeTo(uint8_t *Buf) override; + size_t getSize() const override; + bool empty() const override; + void finalizeContents() override; +}; + // Outputs GNU Hash section. For detailed explanation see: // https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections class GnuHashTableSection final : public SyntheticSection { @@ -992,6 +1002,7 @@ struct InX { static StringTableSection *ShStrTab; static StringTableSection *StrTab; static SymbolTableBaseSection *SymTab; + static SymtabShndxSection* SymTabShndx; }; template <class ELFT> struct In { diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 533ac47f937f..73a97380b54b 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -287,6 +287,7 @@ template <class ELFT> static void createSyntheticSections() { if (Config->Strip != StripPolicy::All) { InX::StrTab = make<StringTableSection>(".strtab", false); InX::SymTab = make<SymbolTableSection<ELFT>>(*InX::StrTab); + InX::SymTabShndx = make<SymtabShndxSection>(); } if (Config->BuildId != BuildIdKind::None) { @@ -409,6 +410,8 @@ template <class ELFT> static void createSyntheticSections() { if (InX::SymTab) Add(InX::SymTab); + if (InX::SymTabShndx) + Add(InX::SymTabShndx); Add(InX::ShStrTab); if (InX::StrTab) Add(InX::StrTab); @@ -518,7 +521,6 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, if (B.isSection()) return false; - if (Config->Discard == DiscardPolicy::None) return true; @@ -1605,6 +1607,15 @@ 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); @@ -1639,12 +1650,13 @@ 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::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}, + {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(); }); if (!Script->HasSectionsCommand && !Config->Relocatable) @@ -1763,6 +1775,8 @@ static bool needsPtLoad(OutputSection *Sec) { static uint64_t computeFlags(uint64_t Flags) { if (Config->Omagic) return PF_R | PF_W | PF_X; + if (Config->ExecuteOnly && (Flags & PF_X)) + return Flags & ~PF_R; if (Config->SingleRoRx && !(Flags & PF_W)) return Flags | PF_X; return Flags; |