From 84c4061b34e048f47e5eb4fbabc1558495e8157c Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Aug 02 2018 17:33:42 +0000 Subject: Vendor import of lld trunk r338536: https://llvm.org/svn/llvm-project/lld/trunk@338536 --- diff --git a/COFF/ICF.cpp b/COFF/ICF.cpp index 6297209..7feb3c4 100644 --- a/COFF/ICF.cpp +++ b/COFF/ICF.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Parallel.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/xxhash.h" #include #include #include @@ -65,13 +66,6 @@ private: std::atomic Repeat = {false}; }; -// Returns a hash value for S. -uint32_t ICF::getHash(SectionChunk *C) { - return hash_combine(C->getOutputCharacteristics(), C->SectionName, - C->Relocs.size(), uint32_t(C->Header->SizeOfRawData), - C->Checksum, C->getContents()); -} - // Returns true if section S is subject of ICF. // // Microsoft's documentation @@ -265,7 +259,7 @@ void ICF::run(ArrayRef Vec) { // Initially, we use hash values to partition sections. for_each(parallel::par, Chunks.begin(), Chunks.end(), [&](SectionChunk *SC) { // Set MSB to 1 to avoid collisions with non-hash classs. - SC->Class[0] = getHash(SC) | (1 << 31); + SC->Class[0] = xxHash64(SC->getContents()) | (1 << 31); }); // From now on, sections in Chunks are ordered so that sections in diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp index d99be9b..acf9a61 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 2d5c23f..ff5e862 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 ec804c5..622324c 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 1fc552f..693dba6 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 void LinkerDriver::link(opt::InputArgList &Args) { @@ -1369,11 +1387,21 @@ template void LinkerDriver::link(opt::InputArgList &Args) { for (StringRef S : Config->Undefined) handleUndefined(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(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(S); + // Return if there were name resolution errors. if (errorCount()) return; diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp index ba413b1..075938b 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 #include @@ -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 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 void ICF::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(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 6da722f..0eb605a 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -494,6 +494,46 @@ void ObjFile::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::createInputSection(const Elf_Shdr &Sec) { ArrayRef 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 d6e9a19..54fb57c 100644 --- a/ELF/InputSection.cpp +++ b/ELF/InputSection.cpp @@ -221,8 +221,8 @@ template Defined *InputSectionBase::getEnclosingFunction(uint64_t Offset) { for (Symbol *B : File->getSymbols()) if (Defined *D = dyn_cast(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& Prologues, - std::vector& MorestackCalls) { + DenseSet &Prologues, std::vector &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 &Prologues) { +static bool enclosingPrologueAdjusted(uint64_t Offset, + const DenseSet &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()->SplitStack) return; - llvm::DenseSet AdjustedPrologues; + DenseSet AdjustedPrologues; std::vector MorestackCalls; for (Relocation &Rel : Relocations) { @@ -1071,8 +1069,7 @@ void MergeInputSection::splitNonStrings(ArrayRef 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 diff --git a/ELF/Options.td b/ELF/Options.td index 73457db..04a4f8f 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 38859e1..ae02434 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -335,7 +335,7 @@ void BuildIdSection::writeBuildId(ArrayRef Buf) { switch (Config->BuildId) { case BuildIdKind::Fast: computeHash(Buf, [](uint8_t *Dest, ArrayRef Arr) { - write64le(Dest, xxHash64(toStringRef(Arr))); + write64le(Dest, xxHash64(Arr)); }); break; case BuildIdKind::Md5: @@ -1935,6 +1935,23 @@ SymbolTableSection::SymbolTableSection(StringTableSection &StrTabSec) this->Entsize = sizeof(Elf_Sym); } +static BssSection *getCommonSec(Symbol *Sym) { + if (!Config->DefineCommon) + if (auto *D = dyn_cast(Sym)) + return dyn_cast_or_null(D->Section); + return nullptr; +} + +static uint32_t getSymSectionIndex(Symbol *Sym) { + if (getCommonSec(Sym)) + return SHN_COMMON; + if (!isa(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 void SymbolTableSection::writeTo(uint8_t *Buf) { // The first entry is a null entry as per the ELF spec. @@ -1956,22 +1973,7 @@ template void SymbolTableSection::writeTo(uint8_t *Buf) { } ESym->st_name = Ent.StrTabOffset; - - // Set a section index. - BssSection *CommonSec = nullptr; - if (!Config->DefineCommon) - if (auto *D = dyn_cast(Sym)) - CommonSec = dyn_cast_or_null(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(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 void SymbolTableSection::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 void SymbolTableSection::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(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(); template GdbIndexSection *GdbIndexSection::create(); diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h index 0366c6c..a780c66 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 struct In { diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 533ac47..73a9738 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -287,6 +287,7 @@ template static void createSyntheticSections() { if (Config->Strip != StripPolicy::All) { InX::StrTab = make(".strtab", false); InX::SymTab = make>(*InX::StrTab); + InX::SymTabShndx = make(); } if (Config->BuildId != BuildIdKind::None) { @@ -409,6 +410,8 @@ template 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 void Writer::finalizeSections() { if (auto *Sec = dyn_cast(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 void Writer::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::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::VerSym, In::VerNeed, InX::Dynamic}, + {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab, + InX::HashTab, InX::SymTab, InX::SymTabShndx, InX::ShStrTab, + InX::StrTab, In::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::VerSym, In::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; diff --git a/docs/index.rst b/docs/index.rst index f4bf3be..2821ce4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,7 +8,7 @@ features that are useful for toolchain developers. The linker supports ELF (Unix), PE/COFF (Windows), Mach-O (macOS) and WebAssembly in descending order of completeness. Internally, LLD consists of several different linkers. The ELF port is the one that will be described in -this document. The PE/COFF port is almost complete except the lack of the +this document. The PE/COFF port is complete, including Windows debug info (PDB) support. The WebAssembly port is still a work in progress (See :doc:`WebAssembly`). The Mach-O port is built based on a different architecture than the others. For the details about Mach-O, please diff --git a/docs/ld.lld.1 b/docs/ld.lld.1 index c966285..0fdfe0a 100644 --- a/docs/ld.lld.1 +++ b/docs/ld.lld.1 @@ -3,7 +3,7 @@ .\" .\" This man page documents only lld's ELF linking support, obtained originally .\" from FreeBSD. -.Dd April 28, 2018 +.Dd July 30, 2018 .Dt LD.LLD 1 .Os .Sh NAME @@ -30,6 +30,8 @@ These options are available: .It Fl -allow-multiple-definition Do not error if a symbol is defined multiple times. The first definition will be used. +.It Fl -apply-dynamic-relocs +Apply link-time values for dynamic relocations. .It Fl -as-needed Only set .Dv DT_NEEDED @@ -38,14 +40,14 @@ for shared libraries if used. Set the .Dv DT_AUXILIARY field to the specified name. -.It Fl -Bdynamic +.It Fl -Bdynamic , Fl -dy Link against shared libraries. -.It Fl -Bstatic +.It Fl -Bstatic , Fl -static , Fl -dn Do not link against shared libraries. -.It Fl -Bsymbolic-functions -Bind defined function symbols locally. .It Fl -Bsymbolic Bind defined symbols locally. +.It Fl -Bsymbolic-functions +Bind defined function symbols locally. .It Fl -build-id Ns = Ns Ar value Generate a build ID note. .Ar value @@ -93,7 +95,9 @@ may be .Cm none or .Cm zlib . -.It Fl -define-common +.It Fl -cref +Output cross reference table. +.It Fl -define-common , Fl d Assign space to common symbols. .It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression Define a symbol alias. @@ -107,9 +111,9 @@ or Demangle symbol names. .It Fl -disable-new-dtags Disable new dynamic tags. -.It Fl -discard-all +.It Fl -discard-all , Fl x Delete all local symbols. -.It Fl -discard-locals +.It Fl -discard-locals , Fl X Delete temporary local symbols. .It Fl -discard-none Keep all symbols in the symbol table. @@ -126,7 +130,7 @@ Request creation of section and .Dv PT_GNU_EH_FRAME segment header. -.It Fl -emit-relocs +.It Fl -emit-relocs , Fl q Generate relocations in the output. .It Fl -enable-new-dtags Enable new dynamic tags. @@ -142,21 +146,21 @@ A value of zero indicates that there is no limit. Report unresolved symbols as errors. .It Fl -exclude-libs Ns = Ns Ar value Exclude static libraries from automatic export. +.It Fl -export-dynamic , Fl E +Put symbols in the dynamic symbol table. .It Fl -export-dynamic-symbol Ns = Ns Ar symbol Include .Ar symbol in the dynamic symbol table. -.It Fl -export-dynamic -Put symbols in the dynamic symbol table. .It Fl -fatal-warnings Treat warnings as errors. -.It Fl -filter Ns = Ns Ar value +.It Fl -filter Ns = Ns Ar value , Fl F Ar value Set the .Dv DT_FILTER field to the specified value. .It Fl -fini Ns = Ns Ar symbol Specify a finalizer function. -.It Fl -format Ns = Ns Ar input-format +.It Fl -format Ns = Ns Ar input-format , Fl b Ar input-format Specify the format of the inputs following this option. .Ar input-format may be one of @@ -196,6 +200,14 @@ Set the base address to .Ar value . .It Fl -init Ns = Ns Ar symbol Specify an initializer function. +.It Fl -keep-unique Ns = Ns Ar symbol +Do not fold +.Ar symbol +during ICF. +.It Fl l Ar libName, Fl -library Ns = Ns Ar libName +Root name of library to use. +.It Fl L Ar dir , Fl -library-path Ns = Ns Ar dir +Add a directory to the library search path. .It Fl -lto-aa-pipeline Ns = Ns Ar value AA pipeline to run during LTO. Used in conjunction with @@ -206,15 +218,11 @@ Passes to run during LTO. Optimization level for LTO. .It Fl -lto-partitions Ns = Ns Ar value Number of LTO codegen partitions. -.It Fl L Ar dir -Add a directory to the library search path. -.It Fl l Ar libName -Root name of library to use. -.It Fl -Map Ns = Ns Ar file -Print a link map to -.Ar file . .It Fl m Ar value Set target emulation. +.It Fl -Map Ns = Ns Ar file , Fl M Ar file +Print a link map to +.Ar file . .It Fl -no-as-needed Always set .Dv DT_NEEDED @@ -243,26 +251,18 @@ Report version scripts that refer undefined symbols. Report unresolved symbols even if the linker is creating a shared library. .It Fl -no-whole-archive Restores the default behavior of loading archive members. -.It Fl -noinhibit-exec -Retain the executable output file whenever it is still usable. .It Fl -no-pie Do not create a position independent executable. +.It Fl -noinhibit-exec +Retain the executable output file whenever it is still usable. .It Fl -nostdlib Only search directories specified on the command line. -.It Fl -oformat Ns = Ns Ar format -Specify the format for the output object file. -The only supported -.Ar format -is -.Cm binary , -which produces output with no ELF header. -.It Fl -omagic -Set the text and data sections to be readable and writable. -.It Fl -opt-remarks-filename Ar file -Write optimization remarks in YAML format to -.Ar file . -.It Fl -opt-remarks-with-hotness -Include hotness information in the optimization remarks file. +.It Fl o Ar path +Write the output executable, library, or object to +.Ar path . +If not specified, +.Dv a.out +is used as a default. .It Fl O Ns Ar value Optimize output file size. .Ar value @@ -279,12 +279,20 @@ Enable string tail merging. .Pp .Fl O Ns Cm 1 is the default. -.It Fl o Ar path -Write the output executable, library, or object to -.Ar path . -If not specified, -.Dv a.out -is used as a default. +.It Fl -oformat Ns = Ns Ar format +Specify the format for the output object file. +The only supported +.Ar format +is +.Cm binary , +which produces output with no ELF header. +.It Fl -omagic , Fl N +Set the text and data sections to be readable and writable. +.It Fl -opt-remarks-filename Ar file +Write optimization remarks in YAML format to +.Ar file . +.It Fl -opt-remarks-with-hotness +Include hotness information in the optimization remarks file. .It Fl -pie Create a position independent executable. .It Fl -print-gc-sections @@ -300,13 +308,13 @@ and .It Fl -pop-state Undo the effect of .Fl -push-state. -.It Fl -relocatable +.It Fl -relocatable , Fl r Create relocatable object file. .It Fl -reproduce Ns = Ns Ar value Dump linker invocation and input files for debugging. .It Fl -retain-symbols-file Ns = Ns Ar file Retain only the symbols listed in the file. -.It Fl -rpath Ns = Ns Ar value +.It Fl -rpath Ns = Ns Ar value , Fl R Ar value Add a .Dv DT_RUNPATH to the output. @@ -316,14 +324,14 @@ The supported values are .Cm windows and .Cm posix . -.It Fl -script Ns = Ns Ar file +.It Fl -script Ns = Ns Ar file , Fl T Ar file Read linker script from .Ar file . -.It Fl -section-start Ns = Ar section Ns = Ns Ar address +.It Fl -section-start Ns = Ns Ar section Ns = Ns Ar address Set address of section. -.It Fl -shared +.It Fl -shared , Fl -Bsharable Build a shared object. -.It Fl -soname Ns = Ns Ar value +.It Fl -soname Ns = Ns Ar value , Fl h Ar value Set .Dv DT_SONAME to @@ -333,9 +341,9 @@ Specifies sections sorting rule when linkerscript is used. .It Fl -start-lib Start a grouping of objects that should be treated as if they were together in an archive. -.It Fl -strip-all +.It Fl -strip-all , Fl s Strip all symbols. -.It Fl -strip-debug +.It Fl -strip-debug , Fl S Strip debugging information. .It Fl -symbol-ordering-file Ns = Ns Ar file Lay out sections in the order specified by @@ -376,6 +384,12 @@ Same as with .Li .data as the sectionname. +.It Fl -Ttext Ns = Ns Ar value +Same as +.Fl -section-start +with +.Li .text +as the sectionname. .It Fl -thinlto-cache-dir Ns = Ns Ar value Path to ThinLTO cached object file directory. .It Fl -thinlto-cache-policy Ns = Ns Ar value @@ -385,33 +399,27 @@ Number of ThinLTO jobs. .It Fl -threads Run the linker multi-threaded. This option is enabled by default. -.It Fl -trace-symbol Ns = Ns Ar symbol -Trace references to -.Ar symbol . .It Fl -trace Print the names of the input files. -.It Fl -Ttext Ns = Ns Ar value -Same as -.Fl -section-start -with -.Li .text -as the sectionname. -.It Fl -undefined Ns = Ns Ar symbol +.It Fl -trace-symbol Ns = Ns Ar symbol , Fl y Ar symbol +Trace references to +.Ar symbol . +.It Fl -undefined Ns = Ns Ar symbol , Fl u Ar symbol Force .Ar symbol to be an undefined symbol during linking. .It Fl -unresolved-symbols Ns = Ns Ar value Determine how to handle unresolved symbols. +.It Fl v +Display the version number and proceed with linking if object files are +specified. +.It Fl V , Fl -version +Display the version number and exit. .It Fl -verbose Verbose mode. .It Fl -version-script Ns = Ns Ar file Read version script from .Ar file . -.It Fl V , Fl -version -Display the version number and exit. -.It Fl v -Display the version number and proceed with linking if object files are -specified. .It Fl -warn-backrefs Warn about reverse or cyclic dependencies to or between static archives. This can be used to ensure linker invocation remains compatible with @@ -432,6 +440,10 @@ Make the main stack executable. Stack permissions are recorded in the .Dv PT_GNU_STACK segment. +.It Cm initfirst +Sets the +.Dv DF_1_INITFIRST +flag to indicate the module should be initialized first. .It Cm muldefs Do not error if a symbol is defined multiple times. The first definition will be used. diff --git a/docs/windows_support.rst b/docs/windows_support.rst index 780c663..a0a2c4d 100644 --- a/docs/windows_support.rst +++ b/docs/windows_support.rst @@ -60,6 +60,13 @@ Debug info link.exe. However, LLD does not support /DEBUG:FASTLINK. +Downloading LLD +=============== + +The Windows version of LLD is included in the `pre-built binaries of LLVM's +releases `_ and in the `LLVM Snapshot +Builds `_. + Building LLD ============ diff --git a/test/ELF/Inputs/arm-vfp-arg-base.s b/test/ELF/Inputs/arm-vfp-arg-base.s new file mode 100644 index 0000000..9625c0a --- /dev/null +++ b/test/ELF/Inputs/arm-vfp-arg-base.s @@ -0,0 +1,16 @@ + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 6 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .eabi_attribute 28, 0 // Tag_ABI_VFP_args = 0 (AAPCS, Base variant) + + .syntax unified + .global f0 + .type f0, %function +f0: bx lr diff --git a/test/ELF/Inputs/arm-vfp-arg-compat.s b/test/ELF/Inputs/arm-vfp-arg-compat.s new file mode 100644 index 0000000..78f6ef6 --- /dev/null +++ b/test/ELF/Inputs/arm-vfp-arg-compat.s @@ -0,0 +1,16 @@ + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 6 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .eabi_attribute 28, 3 // Tag_ABI_VFP_args = 3 (Compatible with all) + + .syntax unified + .global f3 + .type f3, %function +f3: bx lr diff --git a/test/ELF/Inputs/arm-vfp-arg-toolchain.s b/test/ELF/Inputs/arm-vfp-arg-toolchain.s new file mode 100644 index 0000000..bc8eb14 --- /dev/null +++ b/test/ELF/Inputs/arm-vfp-arg-toolchain.s @@ -0,0 +1,15 @@ + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 6 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .eabi_attribute 28, 2 // Tag_ABI_VFP_args = 2 (Toolchain specific) + .syntax unified + .global f2 + .type f1, %function +f2: bx lr diff --git a/test/ELF/Inputs/arm-vfp-arg-vfp.s b/test/ELF/Inputs/arm-vfp-arg-vfp.s new file mode 100644 index 0000000..e8c8a66 --- /dev/null +++ b/test/ELF/Inputs/arm-vfp-arg-vfp.s @@ -0,0 +1,15 @@ + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 6 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .eabi_attribute 28, 1 // Tag_ABI_VFP_args = 1 (AAPCS, VFP variant) + .syntax unified + .global f1 + .type f1, %function +f1: bx lr diff --git a/test/ELF/Inputs/icf-absolute2.s b/test/ELF/Inputs/icf-absolute2.s new file mode 100644 index 0000000..1092c58 --- /dev/null +++ b/test/ELF/Inputs/icf-absolute2.s @@ -0,0 +1,3 @@ +.globl a1, a2 +a1 = 1 +a2 = 2 diff --git a/test/ELF/arm-eabi-version.s b/test/ELF/arm-eabi-version.s index a08374c..4b4f860 100644 --- a/test/ELF/arm-eabi-version.s +++ b/test/ELF/arm-eabi-version.s @@ -9,6 +9,7 @@ _start: bx lr // CHECK: Flags [ +// CHECK-NEXT: 0x200 // CHECK-NEXT: 0x1000000 // CHECK-NEXT: 0x4000000 // CHECK-NEXT: ] diff --git a/test/ELF/arm-tag-vfp-args-errs.s b/test/ELF/arm-tag-vfp-args-errs.s new file mode 100644 index 0000000..622cea0 --- /dev/null +++ b/test/ELF/arm-tag-vfp-args-errs.s @@ -0,0 +1,29 @@ +// REQUIRES:arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-base.s -o %tbase.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-vfp.s -o %tvfp.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-toolchain.s -o %ttoolchain.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +// RUN: not ld.lld %t.o %tbase.o %tvfp.o -o%t 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %tbase.o %ttoolchain.o -o%t 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %tvfp.o %tbase.o -o%t 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %tvfp.o %ttoolchain.o -o%t 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %ttoolchain.o %tbase.o -o%t 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %ttoolchain.o %tvfp.o -o%t 2>&1 | FileCheck %s + +// CHECK: incompatible Tag_ABI_VFP_args + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 6 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .eabi_attribute 28, 3 // Tag_ABI_VFP_args = 3 (Compatible with all) + + .syntax unified + .globl _start + .type _start, %function +_start: bx lr diff --git a/test/ELF/arm-tag-vfp-args-illegal.s b/test/ELF/arm-tag-vfp-args-illegal.s new file mode 100644 index 0000000..471a024 --- /dev/null +++ b/test/ELF/arm-tag-vfp-args-illegal.s @@ -0,0 +1,21 @@ +// REQUIRES:arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +// RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s + +// CHECK: arm-tag-vfp-args-illegal.s.tmp.o: unknown Tag_ABI_VFP_args value: 5 + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 6 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + .eabi_attribute 28, 5 // Tag_ABI_VFP_args = 5 (Illegal value) + + .syntax unified + .globl _start + .type _start, %function +_start: bx lr diff --git a/test/ELF/arm-tag-vfp-args.s b/test/ELF/arm-tag-vfp-args.s new file mode 100644 index 0000000..b0ff095 --- /dev/null +++ b/test/ELF/arm-tag-vfp-args.s @@ -0,0 +1,72 @@ +// REQUIRES:arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-base.s -o %tbase.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-vfp.s -o %tvfp.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-toolchain.s -o %ttoolchain.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-compat.s -o %tcompat.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o + +// The default for this file is 0 (Base AAPCS) +// RUN: ld.lld %t.o -o %tdefault +// RUN: llvm-readobj -file-headers %tdefault | FileCheck -check-prefix=CHECK-BASE %s + +// Expect explicit Base AAPCS. +// RUN: ld.lld %t.o %tbase.o -o %tbase +// RUN: llvm-readobj -file-headers %tbase | FileCheck -check-prefix=CHECK-BASE %s + +// Expect explicit Base AAPCS when linking Base and Compatible. +// RUN: ld.lld %t.o %tbase.o %tcompat.o -o %tbasecompat +// RUN: llvm-readobj -file-headers %tbasecompat | FileCheck -check-prefix=CHECK-BASE %s + +// CHECK-BASE: Flags [ (0x5000200) +// CHECK-BASE-NEXT: 0x200 +// CHECK-BASE-NEXT: 0x1000000 +// CHECK-BASE-NEXT: 0x4000000 +// CHECK-BASE-NEXT: ] + +// Expect Hard float VFP AAPCS +// RUN: ld.lld %t.o %tvfp.o -o %tvfp +// RUN: llvm-readobj -file-headers %tvfp | FileCheck -check-prefix=CHECK-VFP %s + +// Expect Hard float VFP AAPCS when linking VFP and Compatible +// RUN: ld.lld %t.o %tvfp.o %tcompat.o -o %tvfpcompat +// RUN: llvm-readobj -file-headers %tvfpcompat | FileCheck -check-prefix=CHECK-VFP %s + +// CHECK-VFP: Flags [ (0x5000400) +// CHECK-VFP-NEXT: 0x400 +// CHECK-VFP-NEXT: 0x1000000 +// CHECK-VFP-NEXT: 0x4000000 +// CHECK-VFP-NEXT: ] + +// Expect Toolchain specifc to not use either Base or VFP AAPCS +// RUN: ld.lld %t.o %ttoolchain.o -o %ttoolchain +// RUN: llvm-readobj -file-headers %ttoolchain | FileCheck -check-prefix=CHECK-TOOLCHAIN %s + +// Expect Toolchain and Compatible to have same affect as Toolchain. +// RUN: ld.lld %t.o %ttoolchain.o %tcompat.o -o %ttoolchaincompat +// RUN: llvm-readobj -file-headers %ttoolchaincompat | FileCheck -check-prefix=CHECK-TOOLCHAIN %s + +// CHECK-TOOLCHAIN: Flags [ (0x5000000) +// CHECK-TOOLCHAIN-NEXT: 0x1000000 +// CHECK-TOOLCHAIN-NEXT: 0x4000000 +// CHECK-TOOLCHAIN-NEXT: ] + + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 6 + .eabi_attribute 34, 1 + .eabi_attribute 18, 4 + // We do not specify Tag_ABI_VFP_args (.eabi_attribute 28) in this file. + // When omitted the value of the tag defaults to 0, however if there + // are other files with explicit Tag_ABI_VFP_args we use that in + // preference. + + + .syntax unified + .globl _start + .type _start, %function +_start: bx lr diff --git a/test/ELF/execute-only-mixed-data.s b/test/ELF/execute-only-mixed-data.s new file mode 100644 index 0000000..6ef6236 --- /dev/null +++ b/test/ELF/execute-only-mixed-data.s @@ -0,0 +1,26 @@ +// REQUIRES: aarch64 + +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o + +// RUN: echo "SECTIONS \ +// RUN: { \ +// RUN: .text : { *(.text) *(.rodata.foo) } \ +// RUN: .rodata : { *(.rodata.bar) } \ +// RUN: }" > %t.lds +// RUN: not ld.lld -T%t.lds %t.o -o %t -execute-only 2>&1 | FileCheck %s + +// RUN: echo "SECTIONS \ +// RUN: { \ +// RUN: .text : { *(.text) } \ +// RUN: .rodata : { *(.rodata.bar) *(.rodata.foo) } \ +// RUN: }" > %t.lds +// RUN: ld.lld -T%t.lds %t.o -o %t -execute-only 2>&1 + +// CHECK: -execute-only does not support intermingling data and code + + br lr + +.section .rodata.foo +.word 0x1 +.section .rodata.bar +.word 0x2 diff --git a/test/ELF/execute-only.s b/test/ELF/execute-only.s new file mode 100644 index 0000000..7a825cb --- /dev/null +++ b/test/ELF/execute-only.s @@ -0,0 +1,10 @@ +// REQUIRES: aarch64 + +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o +// RUN: ld.lld -Ttext=0xcafe0000 %t.o -o %t.so -shared -execute-only +// RUN: llvm-readelf -l %t.so | FileCheck %s + +// CHECK: LOAD {{.*}} 0x00000000cafe0000 0x000004 0x000004 E 0x{{.*}} +// CHECK-NOT: LOAD {{.*}} 0x00000000cafe0000 0x000004 0x000004 R E 0x{{.*}} + + br lr diff --git a/test/ELF/hexagon.s b/test/ELF/hexagon.s index 8c824ea..1b32733 100644 --- a/test/ELF/hexagon.s +++ b/test/ELF/hexagon.s @@ -4,6 +4,13 @@ # RUN: ld.lld %t2 %t -o %t3 # RUN: llvm-objdump -d %t3 | FileCheck %s +# Note: 69632 == 0x11000 +# R_HEX_32_6_X +# R_HEX_12_X +if (p0) r0 = ##_start +# CHECK: immext(#69632) +# CHECK: if (p0) r0 = ##69632 + # R_HEX_B15_PCREL if (p0) jump:nt #_start # CHECK: if (p0) jump:nt 0x11000 diff --git a/test/ELF/icf-absolute2.s b/test/ELF/icf-absolute2.s new file mode 100644 index 0000000..37e26a9 --- /dev/null +++ b/test/ELF/icf-absolute2.s @@ -0,0 +1,21 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-absolute2.s -o %t2 +# RUN: ld.lld %t %t2 -o /dev/null --icf=all --print-icf-sections | FileCheck -allow-empty %s + +## Test we do not crash and do not fold sections which relocations reffering to +## absolute symbols with a different values. +# CHECK-NOT: selected + +.globl _start, f1, f2 +_start: + ret + +.section .text.f1, "ax" +f1: + .byte a1 + +.section .text.f2, "ax" +f2: + .byte a2 diff --git a/test/ELF/icf-safe.s b/test/ELF/icf-safe.s index b001fcc..2ced78f 100644 --- a/test/ELF/icf-safe.s +++ b/test/ELF/icf-safe.s @@ -10,10 +10,6 @@ # RUN: ld.lld %t1.o %t2.o -o %t2 --icf=all --print-icf-sections --export-dynamic | FileCheck --check-prefix=ALL-EXPORT %s # RUN: ld.lld %t1copy.o -o %t4 --icf=safe 2>&1 | FileCheck --check-prefix=OBJCOPY %s -# CHECK-NOT: selected section {{.*}}:(.rodata.l1) -# CHECK: selected section {{.*}}:(.rodata.l3) -# CHECK: removing identical section {{.*}}:(.rodata.l4) - # CHECK-NOT: selected section {{.*}}:(.text.f1) # CHECK: selected section {{.*}}:(.text.f3) # CHECK: removing identical section {{.*}}:(.text.f4) @@ -22,6 +18,10 @@ # CHECK: selected section {{.*}}:(.rodata.h3) # CHECK: removing identical section {{.*}}:(.rodata.h4) +# CHECK-NOT: selected section {{.*}}:(.rodata.l1) +# CHECK: selected section {{.*}}:(.rodata.l3) +# CHECK: removing identical section {{.*}}:(.rodata.l4) + # CHECK-NOT: selected section {{.*}}:(.rodata.g1) # CHECK: selected section {{.*}}:(.rodata.g3) # CHECK: removing identical section {{.*}}:(.rodata.g4) @@ -30,26 +30,26 @@ # With --icf=all address-significance implies keep-unique only for rodata, not # text. -# ALL-NOT: selected section {{.*}}:(.rodata.l1) -# ALL: selected section {{.*}}:(.rodata.l3) -# ALL: removing identical section {{.*}}:(.rodata.l4) - # ALL: selected section {{.*}}:(.text.f3) # ALL: removing identical section {{.*}}:(.text.f4) -# ALL: selected section {{.*}}:(.text.f1) -# ALL: removing identical section {{.*}}:(.text.f2) -# ALL: removing identical section {{.*}}:(.text.non_addrsig1) -# ALL: removing identical section {{.*}}:(.text.non_addrsig2) - # ALL-NOT: selected section {{.*}}:(.rodata.h1) # ALL: selected section {{.*}}:(.rodata.h3) # ALL: removing identical section {{.*}}:(.rodata.h4) +# ALL-NOT: selected section {{.*}}:(.rodata.l1) +# ALL: selected section {{.*}}:(.rodata.l3) +# ALL: removing identical section {{.*}}:(.rodata.l4) + # ALL-NOT: selected section {{.*}}:(.rodata.g1) # ALL: selected section {{.*}}:(.rodata.g3) # ALL: removing identical section {{.*}}:(.rodata.g4) +# ALL: selected section {{.*}}:(.text.f1) +# ALL: removing identical section {{.*}}:(.text.f2) +# ALL: removing identical section {{.*}}:(.text.non_addrsig1) +# ALL: removing identical section {{.*}}:(.text.non_addrsig2) + # llvm-mc normally emits an empty .text section into every object file. Since # nothing actually refers to it via a relocation, it doesn't have any associated # symbols (thus nor can anything refer to it via a relocation, making it safe to @@ -58,36 +58,36 @@ # STB_LOCAL or STV_HIDDEN symbols. The dynsym entries should have prevented # anything else from being merged. # EXPORT-NOT: selected section -# EXPORT: selected section {{.*}}:(.rodata.l3) -# EXPORT: removing identical section {{.*}}:(.rodata.l4) -# EXPORT-NOT: selected section # EXPORT: selected section {{.*}}:(.rodata.h3) # EXPORT: removing identical section {{.*}}:(.rodata.h4) # EXPORT-NOT: selected section # EXPORT: selected section {{.*}}:(.text) # EXPORT: removing identical section {{.*}}:(.text) # EXPORT-NOT: selected section +# EXPORT: selected section {{.*}}:(.rodata.l3) +# EXPORT: removing identical section {{.*}}:(.rodata.l4) +# EXPORT-NOT: selected section # If --icf=all is specified when exporting we can also merge the exported text # sections, but not the exported rodata. # ALL-EXPORT-NOT: selected section -# ALL-EXPORT: selected section {{.*}}:(.rodata.l3) -# ALL-EXPORT: removing identical section {{.*}}:(.rodata.l4) -# ALL-EXPORT-NOT: selected section # ALL-EXPORT: selected section {{.*}}:(.text.f3) # ALL-EXPORT: removing identical section {{.*}}:(.text.f4) # ALL-EXPORT-NOT: selected section -# ALL-EXPORT: selected section {{.*}}:(.text.f1) -# ALL-EXPORT: removing identical section {{.*}}:(.text.f2) -# ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig1) -# ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig2) -# ALL-EXPORT-NOT: selected section # ALL-EXPORT: selected section {{.*}}:(.rodata.h3) # ALL-EXPORT: removing identical section {{.*}}:(.rodata.h4) # ALL-EXPORT-NOT: selected section # ALL-EXPORT: selected section {{.*}}:(.text) # ALL-EXPORT: removing identical section {{.*}}:(.text) # ALL-EXPORT-NOT: selected section +# ALL-EXPORT: selected section {{.*}}:(.rodata.l3) +# ALL-EXPORT: removing identical section {{.*}}:(.rodata.l4) +# ALL-EXPORT-NOT: selected section +# ALL-EXPORT: selected section {{.*}}:(.text.f1) +# ALL-EXPORT: removing identical section {{.*}}:(.text.f2) +# ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig1) +# ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig2) +# ALL-EXPORT-NOT: selected section # OBJCOPY: --icf=safe is incompatible with object files created using objcopy or ld -r diff --git a/test/ELF/icf17.s b/test/ELF/icf17.s new file mode 100644 index 0000000..5d28aeb --- /dev/null +++ b/test/ELF/icf17.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 +# RUN: ld.lld %t1 -o /dev/null --icf=all --print-icf-sections 2>&1 | FileCheck -allow-empty %s + +# CHECK-NOT: selected + +.section .text +.globl _start +_start: + ret + +.section .aaa, "ax",%progbits,unique,1 +.quad _start + +.section .aaa, "axS",%progbits,unique,2 +.quad _start diff --git a/test/ELF/linkerscript/orphan-report.s b/test/ELF/linkerscript/orphan-report.s index 241857b..903ef79 100644 --- a/test/ELF/linkerscript/orphan-report.s +++ b/test/ELF/linkerscript/orphan-report.s @@ -36,6 +36,7 @@ # REPORT-NEXT: :(.plt) is being placed in '.plt' # REPORT-NEXT: :(.eh_frame) is being placed in '.eh_frame' # REPORT-NEXT: :(.symtab) is being placed in '.symtab' +# REPORT-NEXT: :(.symtab_shndxr) is being placed in '.symtab_shndxr' # REPORT-NEXT: :(.shstrtab) is being placed in '.shstrtab' # REPORT-NEXT: :(.strtab) is being placed in '.strtab' diff --git a/test/ELF/lto/Inputs/libcall-archive.ll b/test/ELF/lto/Inputs/libcall-archive.ll new file mode 100644 index 0000000..4e6421c --- /dev/null +++ b/test/ELF/lto/Inputs/libcall-archive.ll @@ -0,0 +1,6 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @memcpy() { + ret void +} diff --git a/test/ELF/lto/libcall-archive.ll b/test/ELF/lto/libcall-archive.ll new file mode 100644 index 0000000..731e259 --- /dev/null +++ b/test/ELF/lto/libcall-archive.ll @@ -0,0 +1,20 @@ +; RUN: rm -f %t.a +; RUN: llvm-as -o %t.o %s +; RUN: llvm-as -o %t2.o %S/Inputs/libcall-archive.ll +; RUN: llvm-ar rcs %t.a %t2.o +; RUN: ld.lld -o %t %t.o %t.a +; RUN: llvm-nm %t | FileCheck %s + +; CHECK: T _start +; CHECK: T memcpy + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @_start(i8* %a, i8* %b) { +entry: + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 1024, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) diff --git a/test/ELF/oformat-binary.s b/test/ELF/oformat-binary.s index 44c7b5a..e68f07c 100644 --- a/test/ELF/oformat-binary.s +++ b/test/ELF/oformat-binary.s @@ -19,6 +19,8 @@ # RUN: | FileCheck %s --check-prefix ERR # ERR: unknown --oformat value: foo +# RUN: ld.lld -o /dev/null %t --oformat elf + .text .align 4 .globl _start diff --git a/test/ELF/relocatable-many-sections.s b/test/ELF/relocatable-many-sections.s index df22154..347f3f7 100644 --- a/test/ELF/relocatable-many-sections.s +++ b/test/ELF/relocatable-many-sections.s @@ -1,20 +1,32 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o # RUN: ld.lld -r %t.o -o %t -# RUN: llvm-readobj -file-headers %t | FileCheck %s -## Check we are able to emit a valid ELF header when -## sections amount is greater than SHN_LORESERVE. -# CHECK: ElfHeader { -# CHECK: SectionHeaderCount: 0 (65541) -# CHECK-NEXT: StringTableSectionIndex: 65535 (65539) +## Check we are able to link against relocatable file produced. +# RUN: ld.lld %t -o %t.out -## Check that 65539 is really the index of .shstrtab section. -# RUN: llvm-objdump -section-headers -section=.shstrtab %t \ -# RUN: | FileCheck %s --check-prefix=SHSTRTAB -# SHSTRTAB: Sections: -# SHSTRTAB-NEXT: Idx Name -# SHSTRTAB-NEXT: 65539 .shstrtab +## Check we emit a valid ELF header when +## sections amount is greater than SHN_LORESERVE. +# RUN: llvm-readobj -file-headers %t | FileCheck %s --check-prefix=HDR +# HDR: ElfHeader { +# HDR: SectionHeaderCount: 0 (65543) +# HDR-NEXT: StringTableSectionIndex: 65535 (65541) + +## Check that: +## 1) 65541 is the index of .shstrtab section. +## 2) .symtab_shndxr is linked with .symtab. +## 3) .symtab_shndxr entry size and alignment == 4. +## 4) .symtab_shndxr has size equal to +## (sizeof(.symtab) / entsize(.symtab)) * entsize(.symtab_shndxr) = 0x4 * 0x180048 / 0x18 == 0x04000c +# RUN: llvm-readelf -sections -symbols %t | FileCheck %s +## [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: [65538] .bar +# CHECK-NEXT: [65539] .symtab SYMTAB 0000000000000000 000040 180078 18 65542 65539 8 +# CHECK-NEXT: [65540] .symtab_shndxr SYMTAB SECTION INDICES 0000000000000000 1800b8 040014 04 65539 0 4 +# CHECK-NEXT: [65541] .shstrtab STRTAB 0000000000000000 1c00cc 0f0035 00 0 0 1 +# CHECK-NEXT: [65542] .strtab STRTAB 0000000000000000 2b0101 00000c 00 +# 5) Check we are able to represent symbol foo with section (.bar) index > 0xFF00 (SHN_LORESERVE). +# CHECK: GLOBAL DEFAULT 65538 foo .macro gen_sections4 x .section a\x @@ -88,5 +100,10 @@ gen_sections16384 b gen_sections16384 c gen_sections16384 d +.section .bar +.global foo +foo: + +.section .text, "ax" .global _start _start: