Index: vendor/lld/dist/COFF/ICF.cpp =================================================================== --- vendor/lld/dist/COFF/ICF.cpp (revision 337144) +++ vendor/lld/dist/COFF/ICF.cpp (revision 337145) @@ -1,307 +1,301 @@ //===- ICF.cpp ------------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // ICF is short for Identical Code Folding. That is a size optimization to // identify and merge two or more read-only sections (typically functions) // that happened to have the same contents. It usually reduces output size // by a few percent. // // On Windows, ICF is enabled by default. // // See ELF/ICF.cpp for the details about the algortihm. // //===----------------------------------------------------------------------===// #include "ICF.h" #include "Chunks.h" #include "Symbols.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Timer.h" #include "llvm/ADT/Hashing.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Parallel.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/xxhash.h" #include #include #include using namespace llvm; namespace lld { namespace coff { static Timer ICFTimer("ICF", Timer::root()); class ICF { public: void run(ArrayRef V); private: void segregate(size_t Begin, size_t End, bool Constant); bool assocEquals(const SectionChunk *A, const SectionChunk *B); bool equalsConstant(const SectionChunk *A, const SectionChunk *B); bool equalsVariable(const SectionChunk *A, const SectionChunk *B); uint32_t getHash(SectionChunk *C); bool isEligible(SectionChunk *C); size_t findBoundary(size_t Begin, size_t End); void forEachClassRange(size_t Begin, size_t End, std::function Fn); void forEachClass(std::function Fn); std::vector Chunks; int Cnt = 0; 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 // (https://msdn.microsoft.com/en-us/library/bxwfs976.aspx; visited April // 2017) says that /opt:icf folds both functions and read-only data. // Despite that, the MSVC linker folds only functions. We found // a few instances of programs that are not safe for data merging. // Therefore, we merge only functions just like the MSVC tool. However, we also // merge read-only sections in a couple of cases where the address of the // section is insignificant to the user program and the behaviour matches that // of the Visual C++ linker. bool ICF::isEligible(SectionChunk *C) { // Non-comdat chunks, dead chunks, and writable chunks are not elegible. bool Writable = C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE; if (!C->isCOMDAT() || !C->isLive() || Writable) return false; // Code sections are eligible. if (C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE) return true; // .pdata and .xdata unwind info sections are eligible. StringRef OutSecName = C->getSectionName().split('$').first; if (OutSecName == ".pdata" || OutSecName == ".xdata") return true; // So are vtables. return C->Sym && C->Sym->getName().startswith("??_7"); } // Split an equivalence class into smaller classes. void ICF::segregate(size_t Begin, size_t End, bool Constant) { while (Begin < End) { // Divide [Begin, End) into two. Let Mid be the start index of the // second group. auto Bound = std::stable_partition( Chunks.begin() + Begin + 1, Chunks.begin() + End, [&](SectionChunk *S) { if (Constant) return equalsConstant(Chunks[Begin], S); return equalsVariable(Chunks[Begin], S); }); size_t Mid = Bound - Chunks.begin(); // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an // equivalence class ID because every group ends with a unique index. for (size_t I = Begin; I < Mid; ++I) Chunks[I]->Class[(Cnt + 1) % 2] = Mid; // If we created a group, we need to iterate the main loop again. if (Mid != End) Repeat = true; Begin = Mid; } } // Returns true if two sections' associative children are equal. bool ICF::assocEquals(const SectionChunk *A, const SectionChunk *B) { auto ChildClasses = [&](const SectionChunk *SC) { std::vector Classes; for (const SectionChunk *C : SC->children()) if (!C->SectionName.startswith(".debug") && C->SectionName != ".gfids$y" && C->SectionName != ".gljmp$y") Classes.push_back(C->Class[Cnt % 2]); return Classes; }; return ChildClasses(A) == ChildClasses(B); } // Compare "non-moving" part of two sections, namely everything // except relocation targets. bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) { if (A->Relocs.size() != B->Relocs.size()) return false; // Compare relocations. auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { if (R1.Type != R2.Type || R1.VirtualAddress != R2.VirtualAddress) { return false; } Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex); Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex); if (B1 == B2) return true; if (auto *D1 = dyn_cast(B1)) if (auto *D2 = dyn_cast(B2)) return D1->getValue() == D2->getValue() && D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2]; return false; }; if (!std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq)) return false; // Compare section attributes and contents. return A->getOutputCharacteristics() == B->getOutputCharacteristics() && A->SectionName == B->SectionName && A->Header->SizeOfRawData == B->Header->SizeOfRawData && A->Checksum == B->Checksum && A->getContents() == B->getContents() && assocEquals(A, B); } // Compare "moving" part of two sections, namely relocation targets. bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) { // Compare relocations. auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex); Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex); if (B1 == B2) return true; if (auto *D1 = dyn_cast(B1)) if (auto *D2 = dyn_cast(B2)) return D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2]; return false; }; return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq) && assocEquals(A, B); } // Find the first Chunk after Begin that has a different class from Begin. size_t ICF::findBoundary(size_t Begin, size_t End) { for (size_t I = Begin + 1; I < End; ++I) if (Chunks[Begin]->Class[Cnt % 2] != Chunks[I]->Class[Cnt % 2]) return I; return End; } void ICF::forEachClassRange(size_t Begin, size_t End, std::function Fn) { while (Begin < End) { size_t Mid = findBoundary(Begin, End); Fn(Begin, Mid); Begin = Mid; } } // Call Fn on each class group. void ICF::forEachClass(std::function Fn) { // If the number of sections are too small to use threading, // call Fn sequentially. if (Chunks.size() < 1024) { forEachClassRange(0, Chunks.size(), Fn); ++Cnt; return; } // Shard into non-overlapping intervals, and call Fn in parallel. // The sharding must be completed before any calls to Fn are made // so that Fn can modify the Chunks in its shard without causing data // races. const size_t NumShards = 256; size_t Step = Chunks.size() / NumShards; size_t Boundaries[NumShards + 1]; Boundaries[0] = 0; Boundaries[NumShards] = Chunks.size(); for_each_n(parallel::par, size_t(1), NumShards, [&](size_t I) { Boundaries[I] = findBoundary((I - 1) * Step, Chunks.size()); }); for_each_n(parallel::par, size_t(1), NumShards + 1, [&](size_t I) { if (Boundaries[I - 1] < Boundaries[I]) { forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn); } }); ++Cnt; } // Merge identical COMDAT sections. // Two sections are considered the same if their section headers, // contents and relocations are all the same. void ICF::run(ArrayRef Vec) { ScopedTimer T(ICFTimer); // Collect only mergeable sections and group by hash value. uint32_t NextId = 1; for (Chunk *C : Vec) { if (auto *SC = dyn_cast(C)) { if (isEligible(SC)) Chunks.push_back(SC); else SC->Class[0] = NextId++; } } // Make sure that ICF doesn't merge sections that are being handled by string // tail merging. for (auto &P : MergeChunk::Instances) for (SectionChunk *SC : P.second->Sections) SC->Class[0] = NextId++; // 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 // the same group are consecutive in the vector. std::stable_sort(Chunks.begin(), Chunks.end(), [](SectionChunk *A, SectionChunk *B) { return A->Class[0] < B->Class[0]; }); // Compare static contents and assign unique IDs for each static content. forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); }); // Split groups by comparing relocations until convergence is obtained. do { Repeat = false; forEachClass( [&](size_t Begin, size_t End) { segregate(Begin, End, false); }); } while (Repeat); log("ICF needed " + Twine(Cnt) + " iterations"); // Merge sections in the same classs. forEachClass([&](size_t Begin, size_t End) { if (End - Begin == 1) return; log("Selected " + Chunks[Begin]->getDebugName()); for (size_t I = Begin + 1; I < End; ++I) { log(" Removed " + Chunks[I]->getDebugName()); Chunks[Begin]->replace(Chunks[I]); } }); } // Entry point to ICF. void doICF(ArrayRef Chunks) { ICF().run(Chunks); } } // namespace coff } // namespace lld Index: vendor/lld/dist/ELF/Arch/ARM.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/ARM.cpp (revision 337144) +++ vendor/lld/dist/ELF/Arch/ARM.cpp (revision 337145) @@ -1,575 +1,584 @@ //===- ARM.cpp ------------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputFiles.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" #include "Thunks.h" #include "lld/Common/ErrorHandler.h" #include "llvm/Object/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; using namespace llvm::support::endian; using namespace llvm::ELF; using namespace lld; using namespace lld::elf; namespace { class ARM final : public TargetInfo { public: ARM(); uint32_t calcEFlags() const override; RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const override; RelType getDynRel(RelType Type) const override; int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override; void writePltHeader(uint8_t *Buf) const override; void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; void addPltSymbols(InputSection &IS, uint64_t Off) const override; void addPltHeaderSymbols(InputSection &ISD) const override; bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, uint64_t BranchAddr, const Symbol &S) const override; bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; }; } // namespace ARM::ARM() { CopyRel = R_ARM_COPY; RelativeRel = R_ARM_RELATIVE; IRelativeRel = R_ARM_IRELATIVE; GotRel = R_ARM_GLOB_DAT; PltRel = R_ARM_JUMP_SLOT; TlsGotRel = R_ARM_TLS_TPOFF32; TlsModuleIndexRel = R_ARM_TLS_DTPMOD32; TlsOffsetRel = R_ARM_TLS_DTPOFF32; GotBaseSymInGotPlt = false; GotEntrySize = 4; GotPltEntrySize = 4; PltEntrySize = 16; PltHeaderSize = 32; TrapInstr = 0xd4d4d4d4; // ARM uses Variant 1 TLS TcbSize = 8; NeedsThunks = true; // The placing of pre-created ThunkSections is controlled by the // ThunkSectionSpacing parameter. The aim is to place the // ThunkSection such that all branches from the InputSections prior to the // ThunkSection can reach a Thunk placed at the end of the ThunkSection. // Graphically: // | up to ThunkSectionSpacing .text input sections | // | ThunkSection | // | up to ThunkSectionSpacing .text input sections | // | ThunkSection | // Pre-created ThunkSections are spaced roughly 16MiB apart on ARM. This is to // match the most common expected case of a Thumb 2 encoded BL, BLX or B.W // ARM B, BL, BLX range +/- 32MiB // Thumb B.W, BL, BLX range +/- 16MiB // Thumb B.W range +/- 1MiB // If a branch cannot reach a pre-created ThunkSection a new one will be // created so we can handle the rare cases of a Thumb 2 conditional branch. // We intentionally use a lower size for ThunkSectionSpacing than the maximum // branch range so the end of the ThunkSection is more likely to be within // range of the branch instruction that is furthest away. The value we shorten // ThunkSectionSpacing by is set conservatively to allow us to create 16,384 // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to // one of the Thunks going out of range. // FIXME: lld assumes that the Thumb BL and BLX encoding permits the J1 and // J2 bits to be used to extend the branch range. On earlier Architectures // such as ARMv4, ARMv5 and ARMv6 (except ARMv6T2) the range is +/- 4MiB. If // support for the earlier encodings is added then when they are used the // ThunkSectionSpacing will need lowering. ThunkSectionSpacing = 0x1000000 - 0x30000; } 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, const uint8_t *Loc) const { switch (Type) { case R_ARM_THM_JUMP11: return R_PC; case R_ARM_CALL: case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_PREL31: case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: return R_PLT_PC; case R_ARM_GOTOFF32: // (S + A) - GOT_ORG return R_GOTREL; case R_ARM_GOT_BREL: // GOT(S) + A - GOT_ORG return R_GOT_OFF; case R_ARM_GOT_PREL: case R_ARM_TLS_IE32: // GOT(S) + A - P return R_GOT_PC; case R_ARM_SBREL32: return R_ARM_SBREL; case R_ARM_TARGET1: return Config->Target1Rel ? R_PC : R_ABS; case R_ARM_TARGET2: if (Config->Target2 == Target2Policy::Rel) return R_PC; if (Config->Target2 == Target2Policy::Abs) return R_ABS; return R_GOT_PC; case R_ARM_TLS_GD32: return R_TLSGD_PC; case R_ARM_TLS_LDM32: return R_TLSLD_PC; case R_ARM_BASE_PREL: // B(S) + A - P // FIXME: currently B(S) assumed to be .got, this may not hold for all // platforms. return R_GOTONLY_PC; case R_ARM_MOVW_PREL_NC: case R_ARM_MOVT_PREL: case R_ARM_REL32: case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: return R_PC; case R_ARM_NONE: return R_NONE; case R_ARM_TLS_LE32: return R_TLS; default: return R_ABS; } } RelType ARM::getDynRel(RelType Type) const { if ((Type == R_ARM_ABS32) || (Type == R_ARM_TARGET1 && !Config->Target1Rel)) return R_ARM_ABS32; return R_ARM_NONE; } void ARM::writeGotPlt(uint8_t *Buf, const Symbol &) const { write32le(Buf, InX::Plt->getVA()); } void ARM::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { // An ARM entry is the address of the ifunc resolver function. write32le(Buf, S.getVA()); } // Long form PLT Header that does not have any restrictions on the displacement // of the .plt from the .plt.got. static void writePltHeaderLong(uint8_t *Buf) { const uint8_t PltData[] = { 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]! 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8] 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary 0xd4, 0xd4, 0xd4, 0xd4}; memcpy(Buf, PltData, sizeof(PltData)); uint64_t GotPlt = InX::GotPlt->getVA(); uint64_t L1 = InX::Plt->getVA() + 8; write32le(Buf + 16, GotPlt - L1 - 8); } // The default PLT header requires the .plt.got to be within 128 Mb of the // .plt in the positive direction. void ARM::writePltHeader(uint8_t *Buf) const { // Use a similar sequence to that in writePlt(), the difference is the calling // conventions mean we use lr instead of ip. The PLT entry is responsible for // saving lr on the stack, the dynamic loader is responsible for reloading // it. const uint32_t PltData[] = { 0xe52de004, // L1: str lr, [sp,#-4]! 0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4) 0xe28eea00, // add lr, lr, #0x000NN000 &(.got.plt - L1 - 4) 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4) }; uint64_t Offset = InX::GotPlt->getVA() - InX::Plt->getVA() - 4; if (!llvm::isUInt<27>(Offset)) { // We cannot encode the Offset, use the long form. writePltHeaderLong(Buf); return; } write32le(Buf + 0, PltData[0]); write32le(Buf + 4, PltData[1] | ((Offset >> 20) & 0xff)); write32le(Buf + 8, PltData[2] | ((Offset >> 12) & 0xff)); write32le(Buf + 12, PltData[3] | (Offset & 0xfff)); write32le(Buf + 16, TrapInstr); // Pad to 32-byte boundary write32le(Buf + 20, TrapInstr); write32le(Buf + 24, TrapInstr); write32le(Buf + 28, TrapInstr); } void ARM::addPltHeaderSymbols(InputSection &IS) const { addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS); addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS); } // Long form PLT entries that do not have any restrictions on the displacement // of the .plt from the .plt.got. static void writePltLong(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) { const uint8_t PltData[] = { 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip] 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8 }; memcpy(Buf, PltData, sizeof(PltData)); uint64_t L1 = PltEntryAddr + 4; write32le(Buf + 12, GotPltEntryAddr - L1 - 8); } // The default PLT entries require the .plt.got to be within 128 Mb of the // .plt in the positive direction. void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const { // The PLT entry is similar to the example given in Appendix A of ELF for // the Arm Architecture. Instead of using the Group Relocations to find the // optimal rotation for the 8-bit immediate used in the add instructions we // hard code the most compact rotations for simplicity. This saves a load // instruction over the long plt sequences. const uint32_t PltData[] = { 0xe28fc600, // L1: add ip, pc, #0x0NN00000 Offset(&(.plt.got) - L1 - 8 0xe28cca00, // add ip, ip, #0x000NN000 Offset(&(.plt.got) - L1 - 8 0xe5bcf000, // ldr pc, [ip, #0x00000NNN] Offset(&(.plt.got) - L1 - 8 }; uint64_t Offset = GotPltEntryAddr - PltEntryAddr - 8; if (!llvm::isUInt<27>(Offset)) { // We cannot encode the Offset, use the long form. writePltLong(Buf, GotPltEntryAddr, PltEntryAddr, Index, RelOff); return; } write32le(Buf + 0, PltData[0] | ((Offset >> 20) & 0xff)); write32le(Buf + 4, PltData[1] | ((Offset >> 12) & 0xff)); write32le(Buf + 8, PltData[2] | (Offset & 0xfff)); write32le(Buf + 12, TrapInstr); // Pad to 16-byte boundary } void ARM::addPltSymbols(InputSection &IS, uint64_t Off) const { addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS); addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS); } bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, uint64_t BranchAddr, const Symbol &S) const { // If S is an undefined weak symbol and does not have a PLT entry then it // will be resolved as a branch to the next instruction. if (S.isUndefWeak() && !S.isInPlt()) return false; // A state change from ARM to Thumb and vice versa must go through an // interworking thunk if the relocation type is not R_ARM_CALL or // R_ARM_THM_CALL. switch (Type) { case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_JUMP24: // Source is ARM, all PLT entries are ARM so no interworking required. // Otherwise we need to interwork if Symbol has bit 0 set (Thumb). if (Expr == R_PC && ((S.getVA() & 1) == 1)) return true; LLVM_FALLTHROUGH; case R_ARM_CALL: { uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); return !inBranchRange(Type, BranchAddr, Dst); } case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: // Source is Thumb, all PLT entries are ARM so interworking is required. // Otherwise we need to interwork if Symbol has bit 0 clear (ARM). if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0)) return true; LLVM_FALLTHROUGH; case R_ARM_THM_CALL: { uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); return !inBranchRange(Type, BranchAddr, Dst); } } return false; } bool ARM::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { uint64_t Range; uint64_t InstrSize; switch (Type) { case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_JUMP24: case R_ARM_CALL: Range = 0x2000000; InstrSize = 4; break; case R_ARM_THM_JUMP19: Range = 0x100000; InstrSize = 2; break; case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: Range = 0x1000000; InstrSize = 2; break; default: return true; } // PC at Src is 2 instructions ahead, immediate of branch is signed if (Src > Dst) Range -= 2 * InstrSize; else Range += InstrSize; if ((Dst & 0x1) == 0) // Destination is ARM, if ARM caller then Src is already 4-byte aligned. // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure // destination will be 4 byte aligned. Src &= ~0x3; else // Bit 0 == 1 denotes Thumb state, it is not part of the range Dst &= ~0x1; uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src; return Distance <= Range; } void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { switch (Type) { case R_ARM_ABS32: case R_ARM_BASE_PREL: case R_ARM_GLOB_DAT: case R_ARM_GOTOFF32: case R_ARM_GOT_BREL: case R_ARM_GOT_PREL: case R_ARM_REL32: case R_ARM_RELATIVE: case R_ARM_SBREL32: case R_ARM_TARGET1: case R_ARM_TARGET2: case R_ARM_TLS_GD32: case R_ARM_TLS_IE32: case R_ARM_TLS_LDM32: case R_ARM_TLS_LDO32: case R_ARM_TLS_LE32: case R_ARM_TLS_TPOFF32: case R_ARM_TLS_DTPOFF32: write32le(Loc, Val); break; case R_ARM_TLS_DTPMOD32: write32le(Loc, 1); break; case R_ARM_PREL31: checkInt(Loc, Val, 31, Type); write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000)); break; case R_ARM_CALL: // R_ARM_CALL is used for BL and BLX instructions, depending on the // value of bit 0 of Val, we must select a BL or BLX instruction if (Val & 1) { // If bit 0 of Val is 1 the target is Thumb, we must select a BLX. // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1' checkInt(Loc, Val, 26, Type); write32le(Loc, 0xfa000000 | // opcode ((Val & 2) << 23) | // H ((Val >> 2) & 0x00ffffff)); // imm24 break; } if ((read32le(Loc) & 0xfe000000) == 0xfa000000) // BLX (always unconditional) instruction to an ARM Target, select an // unconditional BL. write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff)); // fall through as BL encoding is shared with B LLVM_FALLTHROUGH; case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: checkInt(Loc, Val, 26, Type); write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff)); break; case R_ARM_THM_JUMP11: checkInt(Loc, Val, 12, Type); write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff)); break; case R_ARM_THM_JUMP19: // Encoding T3: Val = S:J2:J1:imm6:imm11:0 checkInt(Loc, Val, 21, Type); write16le(Loc, (read16le(Loc) & 0xfbc0) | // opcode cond ((Val >> 10) & 0x0400) | // S ((Val >> 12) & 0x003f)); // imm6 write16le(Loc + 2, 0x8000 | // opcode ((Val >> 8) & 0x0800) | // J2 ((Val >> 5) & 0x2000) | // J1 ((Val >> 1) & 0x07ff)); // imm11 break; case R_ARM_THM_CALL: // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the // value of bit 0 of Val, we must select a BL or BLX instruction if ((Val & 1) == 0) { // Ensure BLX destination is 4-byte aligned. As BLX instruction may // only be two byte aligned. This must be done before overflow check Val = alignTo(Val, 4); } // Bit 12 is 0 for BLX, 1 for BL write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12); // Fall through as rest of encoding is the same as B.W LLVM_FALLTHROUGH; case R_ARM_THM_JUMP24: // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 // FIXME: Use of I1 and I2 require v6T2ops checkInt(Loc, Val, 25, Type); write16le(Loc, 0xf000 | // opcode ((Val >> 14) & 0x0400) | // S ((Val >> 12) & 0x03ff)); // imm10 write16le(Loc + 2, (read16le(Loc + 2) & 0xd000) | // opcode (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1 (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2 ((Val >> 1) & 0x07ff)); // imm11 break; case R_ARM_MOVW_ABS_NC: case R_ARM_MOVW_PREL_NC: write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) | (Val & 0x0fff)); break; case R_ARM_MOVT_ABS: case R_ARM_MOVT_PREL: checkInt(Loc, Val, 32, Type); write32le(Loc, (read32le(Loc) & ~0x000f0fff) | (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff)); break; case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVT_PREL: // Encoding T1: A = imm4:i:imm3:imm8 checkInt(Loc, Val, 32, Type); write16le(Loc, 0xf2c0 | // opcode ((Val >> 17) & 0x0400) | // i ((Val >> 28) & 0x000f)); // imm4 write16le(Loc + 2, (read16le(Loc + 2) & 0x8f00) | // opcode ((Val >> 12) & 0x7000) | // imm3 ((Val >> 16) & 0x00ff)); // imm8 break; case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVW_PREL_NC: // Encoding T3: A = imm4:i:imm3:imm8 write16le(Loc, 0xf240 | // opcode ((Val >> 1) & 0x0400) | // i ((Val >> 12) & 0x000f)); // imm4 write16le(Loc + 2, (read16le(Loc + 2) & 0x8f00) | // opcode ((Val << 4) & 0x7000) | // imm3 (Val & 0x00ff)); // imm8 break; default: error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); } } int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const { switch (Type) { default: return 0; case R_ARM_ABS32: case R_ARM_BASE_PREL: case R_ARM_GOTOFF32: case R_ARM_GOT_BREL: case R_ARM_GOT_PREL: case R_ARM_REL32: case R_ARM_TARGET1: case R_ARM_TARGET2: case R_ARM_TLS_GD32: case R_ARM_TLS_LDM32: case R_ARM_TLS_LDO32: case R_ARM_TLS_IE32: case R_ARM_TLS_LE32: return SignExtend64<32>(read32le(Buf)); case R_ARM_PREL31: return SignExtend64<31>(read32le(Buf)); case R_ARM_CALL: case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: return SignExtend64<26>(read32le(Buf) << 2); case R_ARM_THM_JUMP11: return SignExtend64<12>(read16le(Buf) << 1); case R_ARM_THM_JUMP19: { // Encoding T3: A = S:J2:J1:imm10:imm6:0 uint16_t Hi = read16le(Buf); uint16_t Lo = read16le(Buf + 2); return SignExtend64<20>(((Hi & 0x0400) << 10) | // S ((Lo & 0x0800) << 8) | // J2 ((Lo & 0x2000) << 5) | // J1 ((Hi & 0x003f) << 12) | // imm6 ((Lo & 0x07ff) << 1)); // imm11:0 } case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: { // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S) // FIXME: I1 and I2 require v6T2ops uint16_t Hi = read16le(Buf); uint16_t Lo = read16le(Buf + 2); return SignExtend64<24>(((Hi & 0x0400) << 14) | // S (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1 (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2 ((Hi & 0x003ff) << 12) | // imm0 ((Lo & 0x007ff) << 1)); // imm11:0 } // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and // MOVT is in the range -32768 <= A < 32768 case R_ARM_MOVW_ABS_NC: case R_ARM_MOVT_ABS: case R_ARM_MOVW_PREL_NC: case R_ARM_MOVT_PREL: { uint64_t Val = read32le(Buf) & 0x000f0fff; return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff)); } case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: { // Encoding T3: A = imm4:i:imm3:imm8 uint16_t Hi = read16le(Buf); uint16_t Lo = read16le(Buf + 2); return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4 ((Hi & 0x0400) << 1) | // i ((Lo & 0x7000) >> 4) | // imm3 (Lo & 0x00ff)); // imm8 } } } TargetInfo *elf::getARMTargetInfo() { static ARM Target; return &Target; } Index: vendor/lld/dist/ELF/Arch/Hexagon.cpp =================================================================== --- vendor/lld/dist/ELF/Arch/Hexagon.cpp (revision 337144) +++ vendor/lld/dist/ELF/Arch/Hexagon.cpp (revision 337145) @@ -1,97 +1,103 @@ //===-- Hexagon.cpp -------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputFiles.h" #include "Symbols.h" #include "Target.h" #include "lld/Common/ErrorHandler.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/ELF.h" #include "llvm/Support/Endian.h" using namespace llvm; using namespace llvm::object; using namespace llvm::support::endian; using namespace llvm::ELF; using namespace lld; using namespace lld::elf; namespace { class Hexagon final : public TargetInfo { public: uint32_t calcEFlags() const override; RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const override; void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; }; } // namespace // Support V60 only at the moment. uint32_t Hexagon::calcEFlags() const { return 0x60; } static uint32_t applyMask(uint32_t Mask, uint32_t Data) { uint32_t Result = 0; size_t Off = 0; for (size_t Bit = 0; Bit != 32; ++Bit) { uint32_t ValBit = (Data >> Off) & 1; uint32_t MaskBit = (Mask >> Bit) & 1; if (MaskBit) { Result |= (ValBit << Bit); ++Off; } } return Result; } RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const { switch (Type) { case R_HEX_B15_PCREL: case R_HEX_B15_PCREL_X: case R_HEX_B22_PCREL: case R_HEX_B22_PCREL_X: case R_HEX_B32_PCREL_X: return R_PC; default: return R_ABS; } } static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); } 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; case R_HEX_B15_PCREL_X: or32le(Loc, applyMask(0x00df20fe, Val & 0x3f)); break; case R_HEX_B22_PCREL: or32le(Loc, applyMask(0x1ff3ffe, Val >> 2)); break; case R_HEX_B22_PCREL_X: or32le(Loc, applyMask(0x1ff3ffe, Val & 0x3f)); break; case R_HEX_B32_PCREL_X: or32le(Loc, applyMask(0x0fff3fff, Val >> 6)); break; default: error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); break; } } TargetInfo *elf::getHexagonTargetInfo() { static Hexagon Target; return &Target; } Index: vendor/lld/dist/ELF/Config.h =================================================================== --- vendor/lld/dist/ELF/Config.h (revision 337144) +++ vendor/lld/dist/ELF/Config.h (revision 337145) @@ -1,279 +1,284 @@ //===- Config.h -------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_CONFIG_H #define LLD_ELF_CONFIG_H #include "lld/Common/ErrorHandler.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Endian.h" #include namespace lld { namespace elf { class InputFile; class InputSectionBase; enum ELFKind { ELFNoneKind, ELF32LEKind, ELF32BEKind, ELF64LEKind, ELF64BEKind }; // For --build-id. enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid }; // For --discard-{all,locals,none}. enum class DiscardPolicy { Default, All, Locals, None }; // For --icf={none,safe,all}. enum class ICFLevel { None, Safe, All }; // For --strip-{all,debug}. enum class StripPolicy { None, All, Debug }; // For --unresolved-symbols. enum class UnresolvedPolicy { ReportError, Warn, Ignore, IgnoreAll }; // For --orphan-handling. enum class OrphanHandlingPolicy { Place, Warn, Error }; // For --sort-section and linkerscript sorting rules. 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; bool HasWildcard; }; // This struct contains symbols version definition that // can be found in version script if it is used for link. struct VersionDefinition { llvm::StringRef Name; uint16_t Id = 0; std::vector Globals; size_t NameOff = 0; // Offset in the string table }; // This struct contains the global configuration for the linker. // Most fields are direct mapping from the command line options // and such fields have the same name as the corresponding options. // Most fields are initialized by the driver. struct Configuration { uint8_t OSABI = 0; llvm::CachePruningPolicy ThinLTOCachePolicy; llvm::StringMap SectionStartMap; llvm::StringRef Chroot; llvm::StringRef DynamicLinker; llvm::StringRef DwoDir; llvm::StringRef Entry; llvm::StringRef Emulation; llvm::StringRef Fini; llvm::StringRef Init; llvm::StringRef LTOAAPipeline; llvm::StringRef LTONewPmPasses; llvm::StringRef LTOObjPath; llvm::StringRef LTOSampleProfile; llvm::StringRef MapFile; llvm::StringRef OutputFile; llvm::StringRef OptRemarksFilename; llvm::StringRef ProgName; llvm::StringRef SoName; llvm::StringRef Sysroot; llvm::StringRef ThinLTOCacheDir; llvm::StringRef ThinLTOIndexOnlyArg; std::pair ThinLTOObjectSuffixReplace; std::pair ThinLTOPrefixReplace; std::string Rpath; std::vector VersionDefinitions; std::vector AuxiliaryList; std::vector FilterList; std::vector SearchPaths; std::vector SymbolOrderingFile; std::vector Undefined; std::vector DynamicList; std::vector VersionScriptGlobals; std::vector VersionScriptLocals; std::vector BuildIdVector; llvm::MapVector, uint64_t> CallGraphProfile; bool AllowMultipleDefinition; bool AndroidPackDynRelocs; bool ARMHasBlx = false; bool ARMHasMovtMovw = false; bool ARMJ1J2BranchEncoding = false; bool AsNeeded = false; bool Bsymbolic; bool BsymbolicFunctions; bool CheckSections; bool CompressDebugSections; bool Cref; bool DefineCommon; bool Demangle = true; bool DisableVerify; bool EhFrameHdr; bool EmitRelocs; bool EnableNewDtags; + bool ExecuteOnly; bool ExportDynamic; bool FixCortexA53Errata843419; bool GcSections; bool GdbIndex; bool GnuHash = false; bool GnuUnique; bool HasDynamicList = false; bool HasDynSymTab; bool IgnoreDataAddressEquality; bool IgnoreFunctionAddressEquality; bool LTODebugPassManager; bool LTONewPassManager; bool MergeArmExidx; bool MipsN32Abi = false; bool NoinhibitExec; bool Nostdlib; bool OFormatBinary; bool Omagic; bool OptRemarksWithHotness; bool Pie; bool PrintGcSections; bool PrintIcfSections; bool Relocatable; bool RelrPackDynRelocs; bool SaveTemps; bool SingleRoRx; bool Shared; bool Static = false; bool SysvHash = false; bool Target1Rel; bool Trace; bool ThinLTOEmitImportsFiles; bool ThinLTOIndexOnly; bool UndefinedVersion; bool UseAndroidRelrTags = false; bool WarnBackrefs; bool WarnCommon; bool WarnMissingEntry; bool WarnSymbolOrdering; bool WriteAddends; bool ZCombreloc; bool ZCopyreloc; bool ZExecstack; bool ZHazardplt; bool ZInitfirst; bool ZKeepTextSectionPrefix; bool ZNodelete; bool ZNodlopen; bool ZNow; bool ZOrigin; bool ZRelro; bool ZRodynamic; bool ZText; bool ZRetpolineplt; bool ZWxneeded; DiscardPolicy Discard; ICFLevel ICF; OrphanHandlingPolicy OrphanHandling; SortSectionPolicy SortSection; 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; uint16_t EMachine = llvm::ELF::EM_NONE; llvm::Optional ImageBase; uint64_t MaxPageSize; uint64_t MipsGotSize; uint64_t ZStackSize; unsigned LTOPartitions; unsigned LTOO; unsigned Optimize; unsigned ThinLTOJobs; // The following config options do not directly correspond to any // particualr command line options. // True if we need to pass through relocations in input files to the // output file. Usually false because we consume relocations. bool CopyRelocs; // True if the target is ELF64. False if ELF32. bool Is64; // True if the target is little-endian. False if big-endian. bool IsLE; // endianness::little if IsLE is true. endianness::big otherwise. llvm::support::endianness Endianness; // True if the target is the little-endian MIPS64. // // The reason why we have this variable only for the MIPS is because // we use this often. Some ELF headers for MIPS64EL are in a // mixed-endian (which is horrible and I'd say that's a serious spec // bug), and we need to know whether we are reading MIPS ELF files or // not in various places. // // (Note that MIPS64EL is not a typo for MIPS64LE. This is the official // name whatever that means. A fun hypothesis is that "EL" is short for // little-endian written in the little-endian order, but I don't know // if that's true.) bool IsMips64EL; // Holds set of ELF header flags for the target. uint32_t EFlags = 0; // The ELF spec defines two types of relocation table entries, RELA and // REL. RELA is a triplet of (offset, info, addend) while REL is a // tuple of (offset, info). Addends for REL are implicit and read from // the location where the relocations are applied. So, REL is more // compact than RELA but requires a bit of more work to process. // // (From the linker writer's view, this distinction is not necessary. // If the ELF had chosen whichever and sticked with it, it would have // been easier to write code to process relocations, but it's too late // to change the spec.) // // Each ABI defines its relocation type. IsRela is true if target // uses RELA. As far as we know, all 64-bit ABIs are using RELA. A // few 32-bit ABIs are using RELA too. bool IsRela; // True if we are creating position-independent code. bool Pic; // 4 for ELF32, 8 for ELF64. int Wordsize; }; // The only instance of Configuration struct. extern Configuration *Config; static inline void errorOrWarn(const Twine &Msg) { if (!Config->NoinhibitExec) error(Msg); else warn(Msg); } } // namespace elf } // namespace lld #endif Index: vendor/lld/dist/ELF/Driver.cpp =================================================================== --- vendor/lld/dist/ELF/Driver.cpp (revision 337144) +++ vendor/lld/dist/ELF/Driver.cpp (revision 337145) @@ -1,1490 +1,1518 @@ //===- Driver.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // The driver drives the entire linking process. It is responsible for // parsing command line options and doing whatever it is instructed to do. // // One notable thing in the LLD's driver when compared to other linkers is // that the LLD's driver is agnostic on the host operating system. // Other linkers usually have implicit default values (such as a dynamic // linker path or library paths) for each host OS. // // I don't think implicit default values are useful because they are // usually explicitly specified by the compiler driver. They can even // be harmful when you are doing cross-linking. Therefore, in LLD, we // simply trust the compiler driver to pass all required options and // don't try to make effort on our side. // //===----------------------------------------------------------------------===// #include "Driver.h" #include "Config.h" #include "Filesystem.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" #include "LinkerScript.h" #include "MarkLive.h" #include "OutputSections.h" #include "ScriptParser.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" #include "Writer.h" #include "lld/Common/Args.h" #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" #include "lld/Common/TargetOptionsCommandFlags.h" #include "lld/Common/Threads.h" #include "lld/Common/Version.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::sys; using namespace lld; using namespace lld::elf; Configuration *elf::Config; LinkerDriver *elf::Driver; static void setConfigs(opt::InputArgList &Args); bool elf::link(ArrayRef Args, bool CanExitEarly, raw_ostream &Error) { errorHandler().LogName = sys::path::filename(Args[0]); errorHandler().ErrorLimitExceededMsg = "too many errors emitted, stopping now (use " "-error-limit=0 to see all errors)"; errorHandler().ErrorOS = &Error; errorHandler().ExitEarly = CanExitEarly; errorHandler().ColorDiagnostics = Error.has_colors(); InputSections.clear(); OutputSections.clear(); Tar = nullptr; BinaryFiles.clear(); BitcodeFiles.clear(); ObjectFiles.clear(); SharedFiles.clear(); Config = make(); Driver = make(); Script = make(); Symtab = make(); Config->ProgName = Args[0]; Driver->main(Args); // Exit immediately if we don't need to return to the caller. // This saves time because the overhead of calling destructors // for all globally-allocated objects is not negligible. if (CanExitEarly) exitLld(errorCount() ? 1 : 0); freeArena(); return !errorCount(); } // Parses a linker -m option. static std::tuple parseEmulation(StringRef Emul) { uint8_t OSABI = 0; StringRef S = Emul; if (S.endswith("_fbsd")) { S = S.drop_back(5); OSABI = ELFOSABI_FREEBSD; } std::pair Ret = StringSwitch>(S) .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec", {ELF64LEKind, EM_AARCH64}) .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM}) .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32ppc", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) .Case("elf64lppc", {ELF64LEKind, EM_PPC64}) .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) .Case("elf_i386", {ELF32LEKind, EM_386}) .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) .Default({ELFNoneKind, EM_NONE}); if (Ret.first == ELFNoneKind) error("unknown emulation: " + Emul); return std::make_tuple(Ret.first, Ret.second, OSABI); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. std::vector> static getArchiveMembers( MemoryBufferRef MB) { std::unique_ptr File = CHECK(Archive::create(MB), MB.getBufferIdentifier() + ": failed to parse archive"); std::vector> V; Error Err = Error::success(); bool AddToTar = File->isThin() && Tar; for (const ErrorOr &COrErr : File->children(Err)) { Archive::Child C = CHECK(COrErr, MB.getBufferIdentifier() + ": could not get the child of the archive"); MemoryBufferRef MBRef = CHECK(C.getMemoryBufferRef(), MB.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); if (AddToTar) Tar->append(relativeToRoot(check(C.getFullName())), MBRef.getBuffer()); V.push_back(std::make_pair(MBRef, C.getChildOffset())); } if (Err) fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + toString(std::move(Err))); // Take ownership of memory buffers created for members of thin archives. for (std::unique_ptr &MB : File->takeThinBuffers()) make>(std::move(MB)); return V; } // Opens a file and create a file object. Path has to be resolved already. void LinkerDriver::addFile(StringRef Path, bool WithLOption) { using namespace sys::fs; Optional Buffer = readFile(Path); if (!Buffer.hasValue()) return; MemoryBufferRef MBRef = *Buffer; if (InBinary) { Files.push_back(make(MBRef)); return; } switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: readLinkerScript(MBRef); return; case file_magic::archive: { // Handle -whole-archive. if (InWholeArchive) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(createObjectFile(P.first, Path, P.second)); return; } std::unique_ptr File = CHECK(Archive::create(MBRef), Path + ": failed to parse archive"); // If an archive file has no symbol table, it is likely that a user // is attempting LTO and using a default ar command that doesn't // understand the LLVM bitcode file. It is a pretty common error, so // we'll handle it as if it had a symbol table. if (!File->isEmpty() && !File->hasSymbolTable()) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(make(P.first, Path, P.second)); return; } // Handle the regular case. Files.push_back(make(std::move(File))); return; } case file_magic::elf_shared_object: if (Config->Relocatable) { error("attempted static link of dynamic object " + Path); return; } // DSOs usually have DT_SONAME tags in their ELF headers, and the // sonames are used to identify DSOs. But if they are missing, // they are identified by filenames. We don't know whether the new // file has a DT_SONAME or not because we haven't parsed it yet. // Here, we set the default soname for the file because we might // need it later. // // If a file was specified by -lfoo, the directory part is not // significant, as a user did not specify it. This behavior is // compatible with GNU. Files.push_back( createSharedFile(MBRef, WithLOption ? path::filename(Path) : Path)); return; case file_magic::bitcode: case file_magic::elf_relocatable: if (InLib) Files.push_back(make(MBRef, "", 0)); else Files.push_back(createObjectFile(MBRef)); break; default: error(Path + ": unknown file type"); } } // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { if (Optional Path = searchLibrary(Name)) addFile(*Path, /*WithLOption=*/true); else error("unable to find library -l" + Name); } // This function is called on startup. We need this for LTO since // LTO calls LLVM functions to compile bitcode files to native code. // Technically this can be delayed until we read bitcode files, but // we don't bother to do lazily because the initialization is fast. static void initLLVM() { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); } // Some command line options or some combinations of them are not allowed. // This function checks for such errors. static void checkOptions(opt::InputArgList &Args) { // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup // table which is a relatively new feature. if (Config->EMachine == EM_MIPS && Config->GnuHash) error("the .gnu.hash section is not compatible with the MIPS target."); if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64) error("--fix-cortex-a53-843419 is only supported on AArch64 targets."); if (Config->Pie && Config->Shared) error("-shared and -pie may not be used together"); if (!Config->Shared && !Config->FilterList.empty()) error("-F may not be used without -shared"); if (!Config->Shared && !Config->AuxiliaryList.empty()) error("-f may not be used without -shared"); if (!Config->Relocatable && !Config->DefineCommon) error("-no-define-common not supported in non relocatable output"); if (Config->Relocatable) { if (Config->Shared) error("-r and -shared may not be used together"); if (Config->GcSections) error("-r and --gc-sections may not be used together"); if (Config->GdbIndex) error("-r and --gdb-index may not be used together"); if (Config->ICF != ICFLevel::None) error("-r and --icf may not be used together"); 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) { if (auto *Arg = Args.getLastArg(OPT_reproduce)) return Arg->getValue(); return getenv("LLD_REPRODUCE"); } static bool hasZOption(opt::InputArgList &Args, StringRef Key) { for (auto *Arg : Args.filtered(OPT_z)) if (Key == Arg->getValue()) return true; return false; } static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2, bool Default) { for (auto *Arg : Args.filtered_reverse(OPT_z)) { if (K1 == Arg->getValue()) return true; if (K2 == Arg->getValue()) return false; } return Default; } static bool isKnown(StringRef S) { return S == "combreloc" || S == "copyreloc" || S == "defs" || S == "execstack" || S == "hazardplt" || S == "initfirst" || S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" || S == "nocombreloc" || S == "nocopyreloc" || S == "nodelete" || S == "nodlopen" || S == "noexecstack" || S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" || S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" || S == "rodynamic" || S == "text" || S == "wxneeded" || S.startswith("max-page-size=") || S.startswith("stack-size="); } // Report an error for an unknown -z option. static void checkZOptions(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_z)) if (!isKnown(Arg->getValue())) error("unknown -z value: " + StringRef(Arg->getValue())); } void LinkerDriver::main(ArrayRef ArgsArr) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); // Interpret this flag early because error() depends on them. errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); // Handle -help if (Args.hasArg(OPT_help)) { printHelp(); return; } // Handle -v or -version. // // A note about "compatible with GNU linkers" message: this is a hack for // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and // still the newest version in March 2017) or earlier to recognize LLD as // a GNU compatible linker. As long as an output for the -v option // contains "GNU" or "with BFD", they recognize us as GNU-compatible. // // This is somewhat ugly hack, but in reality, we had no choice other // than doing this. Considering the very long release cycle of Libtool, // it is not easy to improve it to recognize LLD as a GNU compatible // linker in a timely manner. Even if we can make it, there are still a // lot of "configure" scripts out there that are generated by old version // of Libtool. We cannot convince every software developer to migrate to // the latest version and re-generate scripts. So we have this hack. if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) message(getLLDVersion() + " (compatible with GNU linkers)"); // The behavior of -v or --version is a bit strange, but this is // needed for compatibility with GNU linkers. if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT)) return; if (Args.hasArg(OPT_version)) return; if (const char *Path = getReproduceOption(Args)) { // Note that --reproduce is a debug option so you can ignore it // if you are trying to understand the whole picture of the code. Expected> ErrOrWriter = TarWriter::create(Path, path::stem(Path)); if (ErrOrWriter) { Tar = ErrOrWriter->get(); Tar->append("response.txt", createResponseFile(Args)); Tar->append("version.txt", getLLDVersion() + "\n"); make>(std::move(*ErrOrWriter)); } else { error(Twine("--reproduce: failed to open ") + Path + ": " + toString(ErrOrWriter.takeError())); } } readConfigs(Args); checkZOptions(Args); initLLVM(); createFiles(Args); if (errorCount()) return; inferMachineType(); setConfigs(Args); checkOptions(Args); if (errorCount()) return; switch (Config->EKind) { case ELF32LEKind: link(Args); return; case ELF32BEKind: link(Args); return; case ELF64LEKind: link(Args); return; case ELF64BEKind: link(Args); return; default: llvm_unreachable("unknown Config->EKind"); } } static std::string getRpath(opt::InputArgList &Args) { std::vector V = args::getStrings(Args, OPT_rpath); return llvm::join(V.begin(), V.end(), ":"); } // Determines what we should do if there are remaining unresolved // symbols after the name resolution. static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return UnresolvedPolicy::IgnoreAll; UnresolvedPolicy ErrorOrWarn = Args.hasFlag(OPT_error_unresolved_symbols, OPT_warn_unresolved_symbols, true) ? UnresolvedPolicy::ReportError : UnresolvedPolicy::Warn; // Process the last of -unresolved-symbols, -no-undefined or -z defs. for (auto *Arg : llvm::reverse(Args)) { switch (Arg->getOption().getID()) { case OPT_unresolved_symbols: { StringRef S = Arg->getValue(); if (S == "ignore-all" || S == "ignore-in-object-files") return UnresolvedPolicy::Ignore; if (S == "ignore-in-shared-libs" || S == "report-all") return ErrorOrWarn; error("unknown --unresolved-symbols value: " + S); continue; } case OPT_no_undefined: return ErrorOrWarn; case OPT_z: if (StringRef(Arg->getValue()) == "defs") return ErrorOrWarn; continue; } } // -shared implies -unresolved-symbols=ignore-all because missing // symbols are likely to be resolved at runtime using other DSOs. if (Config->Shared) return UnresolvedPolicy::Ignore; return ErrorOrWarn; } static Target2Policy getTarget2(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_target2, "got-rel"); if (S == "rel") return Target2Policy::Rel; if (S == "abs") return Target2Policy::Abs; if (S == "got-rel") return Target2Policy::GotRel; error("unknown --target2 option: " + S); return Target2Policy::GotRel; } static bool isOutputFormatBinary(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_oformat)) { StringRef S = Arg->getValue(); if (S == "binary") return true; + if (S.startswith("elf")) + return false; error("unknown --oformat value: " + S); } return false; } static DiscardPolicy getDiscard(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return DiscardPolicy::None; auto *Arg = Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none); if (!Arg) return DiscardPolicy::Default; if (Arg->getOption().getID() == OPT_discard_all) return DiscardPolicy::All; if (Arg->getOption().getID() == OPT_discard_locals) return DiscardPolicy::Locals; return DiscardPolicy::None; } static StringRef getDynamicLinker(opt::InputArgList &Args) { auto *Arg = Args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker); if (!Arg || Arg->getOption().getID() == OPT_no_dynamic_linker) return ""; return Arg->getValue(); } static ICFLevel getICF(opt::InputArgList &Args) { auto *Arg = Args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all); if (!Arg || Arg->getOption().getID() == OPT_icf_none) return ICFLevel::None; if (Arg->getOption().getID() == OPT_icf_safe) return ICFLevel::Safe; return ICFLevel::All; } static StripPolicy getStrip(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return StripPolicy::None; auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug); if (!Arg) return StripPolicy::None; if (Arg->getOption().getID() == OPT_strip_all) return StripPolicy::All; return StripPolicy::Debug; } static uint64_t parseSectionAddress(StringRef S, const opt::Arg &Arg) { uint64_t VA = 0; if (S.startswith("0x")) S = S.drop_front(2); if (!to_integer(S, VA, 16)) error("invalid argument: " + toString(Arg)); return VA; } static StringMap getSectionStartMap(opt::InputArgList &Args) { StringMap Ret; for (auto *Arg : Args.filtered(OPT_section_start)) { StringRef Name; StringRef Addr; std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); Ret[Name] = parseSectionAddress(Addr, *Arg); } if (auto *Arg = Args.getLastArg(OPT_Ttext)) Ret[".text"] = parseSectionAddress(Arg->getValue(), *Arg); if (auto *Arg = Args.getLastArg(OPT_Tdata)) Ret[".data"] = parseSectionAddress(Arg->getValue(), *Arg); if (auto *Arg = Args.getLastArg(OPT_Tbss)) Ret[".bss"] = parseSectionAddress(Arg->getValue(), *Arg); return Ret; } static SortSectionPolicy getSortSection(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_sort_section); if (S == "alignment") return SortSectionPolicy::Alignment; if (S == "name") return SortSectionPolicy::Name; if (!S.empty()) error("unknown --sort-section rule: " + S); return SortSectionPolicy::Default; } static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_orphan_handling, "place"); if (S == "warn") return OrphanHandlingPolicy::Warn; if (S == "error") return OrphanHandlingPolicy::Error; if (S != "place") error("unknown --orphan-handling mode: " + S); return OrphanHandlingPolicy::Place; } // Parse --build-id or --build-id= .. role:: none .. role:: partial .. role:: good =============== Windows support =============== LLD supports Windows operating system. When invoked as ``lld-link.exe`` or with ``-flavor link``, the driver for Windows operating system is used to parse command line options, and it drives further linking processes. LLD accepts almost all command line options that the linker shipped with Microsoft Visual C++ (link.exe) supports. The current status is that LLD can link itself on Windows x86/x64 using Visual C++ 2013 as the compiler. Development status ================== Driver :good:`Mostly done`. Some exotic command line options that are not usually used for application develompent, such as ``/DRIVER``, are not supported. Linking against DLL :good:`Done`. LLD can read import libraries needed to link against DLL. Both export-by-name and export-by-ordinal are supported. Linking against static library :good:`Done`. The format of static library (.lib) on Windows is actually the same as on Unix (.a). LLD can read it. Creating DLL :good:`Done`. LLD creates a DLL if ``/DLL`` option is given. Exported functions can be specified either via command line (``/EXPORT``) or via module-definition file (.def). Both export-by-name and export-by-ordinal are supported. Windows resource files support :good:`Done`. If an ``.res`` file is given, LLD converts the file to a COFF file using LLVM's Object library. Safe Structured Exception Handler (SEH) :good:`Done` for both x86 and x64. Module-definition file :partial:`Partially done`. LLD currently recognizes these directives: ``EXPORTS``, ``HEAPSIZE``, ``STACKSIZE``, ``NAME``, and ``VERSION``. Debug info :good:`Done`. LLD can emit PDBs that are at parity with those generated by 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 ============ Using Visual Studio IDE/MSBuild ------------------------------- 1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror), #. run ``cmake -G "Visual Studio 12" `` from VS command prompt, #. open LLVM.sln with Visual Studio, and #. build ``lld`` target in ``lld executables`` folder Alternatively, you can use msbuild if you don't like to work in an IDE:: msbuild LLVM.sln /m /target:"lld executables\lld" MSBuild.exe had been shipped as a component of the .NET framework, but since 2013 it's part of Visual Studio. You can find it at "C:\\Program Files (x86)\\msbuild". You can build LLD as a 64 bit application. To do that, open VS2013 x64 command prompt and run cmake for "Visual Studio 12 Win64" target. Using Ninja ----------- 1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror), #. run ``cmake -G ninja `` from VS command prompt, #. run ``ninja lld`` Index: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-base.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-base.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-base.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-base.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-compat.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-compat.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-compat.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-compat.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-toolchain.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-toolchain.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-toolchain.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-toolchain.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-vfp.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-vfp.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-vfp.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/Inputs/arm-vfp-arg-vfp.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/Inputs/icf-absolute2.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/icf-absolute2.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/icf-absolute2.s (revision 337145) @@ -0,0 +1,3 @@ +.globl a1, a2 +a1 = 1 +a2 = 2 Property changes on: vendor/lld/dist/test/ELF/Inputs/icf-absolute2.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/arm-eabi-version.s =================================================================== --- vendor/lld/dist/test/ELF/arm-eabi-version.s (revision 337144) +++ vendor/lld/dist/test/ELF/arm-eabi-version.s (revision 337145) @@ -1,14 +1,15 @@ // REQUIRES: arm // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o // RUN: ld.lld -static %t.o -o %tout // RUN: llvm-readobj -file-headers %tout | FileCheck %s .syntax unified .text .globl _start _start: bx lr // CHECK: Flags [ +// CHECK-NEXT: 0x200 // CHECK-NEXT: 0x1000000 // CHECK-NEXT: 0x4000000 // CHECK-NEXT: ] Index: vendor/lld/dist/test/ELF/arm-tag-vfp-args-errs.s =================================================================== --- vendor/lld/dist/test/ELF/arm-tag-vfp-args-errs.s (nonexistent) +++ vendor/lld/dist/test/ELF/arm-tag-vfp-args-errs.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/arm-tag-vfp-args-errs.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/arm-tag-vfp-args-illegal.s =================================================================== --- vendor/lld/dist/test/ELF/arm-tag-vfp-args-illegal.s (nonexistent) +++ vendor/lld/dist/test/ELF/arm-tag-vfp-args-illegal.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/arm-tag-vfp-args-illegal.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/arm-tag-vfp-args.s =================================================================== --- vendor/lld/dist/test/ELF/arm-tag-vfp-args.s (nonexistent) +++ vendor/lld/dist/test/ELF/arm-tag-vfp-args.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/arm-tag-vfp-args.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/execute-only-mixed-data.s =================================================================== --- vendor/lld/dist/test/ELF/execute-only-mixed-data.s (nonexistent) +++ vendor/lld/dist/test/ELF/execute-only-mixed-data.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/execute-only-mixed-data.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/execute-only.s =================================================================== --- vendor/lld/dist/test/ELF/execute-only.s (nonexistent) +++ vendor/lld/dist/test/ELF/execute-only.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/execute-only.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/hexagon.s =================================================================== --- vendor/lld/dist/test/ELF/hexagon.s (revision 337144) +++ vendor/lld/dist/test/ELF/hexagon.s (revision 337145) @@ -1,24 +1,31 @@ # REQUIRES: hexagon # RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t # RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %S/Inputs/hexagon.s -o %t2 # 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 # R_HEX_B32_PCREL_X # R_HEX_B15_PCREL_X if (p0) jump:nt ##_start # CHECK: if (p0) jump:nt 0x11000 # R_HEX_B22_PCREL call #_start # CHECK: call 0x11000 # R_HEX_B32_PCREL_X # R_HEX_B22_PCREL_X call ##_start # CHECK: immext(#4294967232) # CHECK: call 0x11000 Index: vendor/lld/dist/test/ELF/icf-absolute2.s =================================================================== --- vendor/lld/dist/test/ELF/icf-absolute2.s (nonexistent) +++ vendor/lld/dist/test/ELF/icf-absolute2.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/icf-absolute2.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/icf-safe.s =================================================================== --- vendor/lld/dist/test/ELF/icf-safe.s (revision 337144) +++ vendor/lld/dist/test/ELF/icf-safe.s (revision 337145) @@ -1,182 +1,182 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o # RUN: llvm-objcopy %t1.o %t1copy.o # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/icf-safe.s -o %t2.o # RUN: ld.lld %t1.o %t2.o -o %t2 --icf=safe --print-icf-sections | FileCheck %s # RUN: ld.lld %t1.o %t2.o -o %t3 --icf=safe --print-icf-sections -shared | FileCheck --check-prefix=EXPORT %s # RUN: ld.lld %t1.o %t2.o -o %t3 --icf=safe --print-icf-sections --export-dynamic | FileCheck --check-prefix=EXPORT %s # RUN: ld.lld %t1.o %t2.o -o %t2 --icf=all --print-icf-sections | FileCheck --check-prefix=ALL %s # 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) # CHECK-NOT: selected section {{.*}}:(.rodata.h1) # 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) # CHECK-NOT: selected section {{.*}}:(.text.non_addrsig{{.}}) # 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 # merge with the empty section in the other input file). Here we check that the # only two sections merged are the two empty sections and the sections with only # 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 .section .text.f1,"ax",@progbits .globl f1 f1: ret .section .text.f2,"ax",@progbits .globl f2 f2: ret .section .text.f3,"ax",@progbits .globl f3 f3: ud2 .section .text.f4,"ax",@progbits .globl f4 f4: ud2 .section .rodata.g1,"a",@progbits .globl g1 g1: .byte 1 .section .rodata.g2,"a",@progbits .globl g2 g2: .byte 1 .section .rodata.g3,"a",@progbits .globl g3 g3: .byte 2 .section .rodata.g4,"a",@progbits .globl g4 g4: .byte 2 .section .rodata.l1,"a",@progbits l1: .byte 3 .section .rodata.l2,"a",@progbits l2: .byte 3 .section .rodata.l3,"a",@progbits l3: .byte 4 .section .rodata.l4,"a",@progbits l4: .byte 4 .section .rodata.h1,"a",@progbits .globl h1 .hidden h1 h1: .byte 5 .section .rodata.h2,"a",@progbits .globl h2 .hidden h2 h2: .byte 5 .section .rodata.h3,"a",@progbits .globl h3 .hidden h3 h3: .byte 6 .section .rodata.h4,"a",@progbits .globl h4 .hidden h4 h4: .byte 6 .addrsig .addrsig_sym f1 .addrsig_sym f2 .addrsig_sym g1 .addrsig_sym g2 .addrsig_sym l1 .addrsig_sym l2 .addrsig_sym h1 .addrsig_sym h2 Index: vendor/lld/dist/test/ELF/icf17.s =================================================================== --- vendor/lld/dist/test/ELF/icf17.s (nonexistent) +++ vendor/lld/dist/test/ELF/icf17.s (revision 337145) @@ -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 Property changes on: vendor/lld/dist/test/ELF/icf17.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/linkerscript/orphan-report.s =================================================================== --- vendor/lld/dist/test/ELF/linkerscript/orphan-report.s (revision 337144) +++ vendor/lld/dist/test/ELF/linkerscript/orphan-report.s (revision 337145) @@ -1,54 +1,55 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: echo "SECTIONS { .text : { *(.text.1) } }" > %t.script ## Check we do not report orphans by default even with -verbose. # RUN: ld.lld -shared -o %t.out --script %t.script %t.o 2>&1 -verbose \ # RUN: | FileCheck %s --check-prefix=DEFAULT # DEFAULT-NOT: placed ## Check --orphan-handling=place has the same behavior as default. # RUN: ld.lld -shared --orphan-handling=place -o %t.out --script %t.script \ # RUN: %t.o 2>&1 -verbose -error-limit=0 | FileCheck %s --check-prefix=DEFAULT ## Check --orphan-handling=error reports errors about orphans. # RUN: not ld.lld -shared --orphan-handling=error -o %t.out --script %t.script \ # RUN: %t.o 2>&1 -verbose -error-limit=0 | FileCheck %s --check-prefix=REPORT # REPORT: {{.*}}.o:(.text) is being placed in '.text' # REPORT-NEXT: {{.*}}.o:(.text.2) is being placed in '.text' # REPORT-NEXT: :(.comment) is being placed in '.comment' # REPORT-NEXT: :(.bss) is being placed in '.bss' # REPORT-NEXT: :(.bss.rel.ro) is being placed in '.bss.rel.ro' # REPORT-NEXT: :(.dynsym) is being placed in '.dynsym' # REPORT-NEXT: :(.gnu.version) is being placed in '.gnu.version' # REPORT-NEXT: :(.gnu.version_r) is being placed in '.gnu.version_r' # REPORT-NEXT: :(.gnu.hash) is being placed in '.gnu.hash' # REPORT-NEXT: :(.hash) is being placed in '.hash' # REPORT-NEXT: :(.dynamic) is being placed in '.dynamic' # REPORT-NEXT: :(.dynstr) is being placed in '.dynstr' # REPORT-NEXT: :(.rela.dyn) is being placed in '.rela.dyn' # REPORT-NEXT: :(.got) is being placed in '.got' # REPORT-NEXT: :(.got.plt) is being placed in '.got.plt' # REPORT-NEXT: :(.got.plt) is being placed in '.got.plt' # REPORT-NEXT: :(.rela.plt) is being placed in '.rela.plt' # REPORT-NEXT: :(.rela.plt) is being placed in '.rela.plt' # REPORT-NEXT: :(.plt) is being placed in '.plt' # 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' ## Check --orphan-handling=warn reports warnings about orphans. # RUN: ld.lld -shared --orphan-handling=warn -o %t.out --script %t.script \ # RUN: %t.o 2>&1 -verbose | FileCheck %s --check-prefix=REPORT # RUN: not ld.lld --orphan-handling=foo -o %t.out --script %t.script %t.o 2>&1 \ # RUN: | FileCheck %s --check-prefix=UNKNOWN # UNKNOWN: unknown --orphan-handling mode: foo .section .text.1,"a" nop .section .text.2,"a" nop Index: vendor/lld/dist/test/ELF/lto/Inputs/libcall-archive.ll =================================================================== --- vendor/lld/dist/test/ELF/lto/Inputs/libcall-archive.ll (nonexistent) +++ vendor/lld/dist/test/ELF/lto/Inputs/libcall-archive.ll (revision 337145) @@ -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 +} Index: vendor/lld/dist/test/ELF/lto/libcall-archive.ll =================================================================== --- vendor/lld/dist/test/ELF/lto/libcall-archive.ll (nonexistent) +++ vendor/lld/dist/test/ELF/lto/libcall-archive.ll (revision 337145) @@ -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) Index: vendor/lld/dist/test/ELF/oformat-binary.s =================================================================== --- vendor/lld/dist/test/ELF/oformat-binary.s (revision 337144) +++ vendor/lld/dist/test/ELF/oformat-binary.s (revision 337145) @@ -1,32 +1,34 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: ld.lld -o %t.out %t --oformat binary # RUN: od -t x1 -v %t.out | FileCheck %s # CHECK: 000000 90 11 22 00 00 00 00 00 # CHECK-NOT: 00000010 ## Check case when linkerscript is used. # RUN: echo "SECTIONS { . = 0x1000; }" > %t.script # RUN: ld.lld -o %t2.out --script %t.script %t --oformat binary # RUN: od -t x1 -v %t2.out | FileCheck %s # RUN: echo "SECTIONS { }" > %t.script # RUN: ld.lld -o %t2.out --script %t.script %t --oformat binary # RUN: od -t x1 -v %t2.out | FileCheck %s # RUN: not ld.lld -o /dev/null %t --oformat foo 2>&1 \ # 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 _start: nop .section .mysec.1,"ax" .byte 0x11 .section .mysec.2,"ax" .byte 0x22 Index: vendor/lld/dist/test/ELF/relocatable-many-sections.s =================================================================== --- vendor/lld/dist/test/ELF/relocatable-many-sections.s (revision 337144) +++ vendor/lld/dist/test/ELF/relocatable-many-sections.s (revision 337145) @@ -1,92 +1,109 @@ # 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 +## Check we are able to link against relocatable file produced. +# RUN: ld.lld %t -o %t.out + +## Check we emit a valid ELF header when ## sections amount is greater than SHN_LORESERVE. -# CHECK: ElfHeader { -# CHECK: SectionHeaderCount: 0 (65541) -# CHECK-NEXT: StringTableSectionIndex: 65535 (65539) +# RUN: llvm-readobj -file-headers %t | FileCheck %s --check-prefix=HDR +# HDR: ElfHeader { +# HDR: SectionHeaderCount: 0 (65543) +# HDR-NEXT: StringTableSectionIndex: 65535 (65541) -## 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 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 .section b\x .section c\x .section d\x .endm .macro gen_sections8 x gen_sections4 a\x gen_sections4 b\x .endm .macro gen_sections16 x gen_sections8 a\x gen_sections8 b\x .endm .macro gen_sections32 x gen_sections16 a\x gen_sections16 b\x .endm .macro gen_sections64 x gen_sections32 a\x gen_sections32 b\x .endm .macro gen_sections128 x gen_sections64 a\x gen_sections64 b\x .endm .macro gen_sections256 x gen_sections128 a\x gen_sections128 b\x .endm .macro gen_sections512 x gen_sections256 a\x gen_sections256 b\x .endm .macro gen_sections1024 x gen_sections512 a\x gen_sections512 b\x .endm .macro gen_sections2048 x gen_sections1024 a\x gen_sections1024 b\x .endm .macro gen_sections4096 x gen_sections2048 a\x gen_sections2048 b\x .endm .macro gen_sections8192 x gen_sections4096 a\x gen_sections4096 b\x .endm .macro gen_sections16384 x gen_sections8192 a\x gen_sections8192 b\x .endm gen_sections16384 a gen_sections16384 b gen_sections16384 c gen_sections16384 d +.section .bar +.global foo +foo: + +.section .text, "ax" .global _start _start: