From owner-svn-src-vendor@freebsd.org Thu Jul 13 19:26:10 2017 Return-Path: Delivered-To: svn-src-vendor@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 93595DAC328; Thu, 13 Jul 2017 19:26:10 +0000 (UTC) (envelope-from dim@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 30282987; Thu, 13 Jul 2017 19:26:10 +0000 (UTC) (envelope-from dim@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v6DJQ9EA036823; Thu, 13 Jul 2017 19:26:09 GMT (envelope-from dim@FreeBSD.org) Received: (from dim@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v6DJQ7U5036801; Thu, 13 Jul 2017 19:26:07 GMT (envelope-from dim@FreeBSD.org) Message-Id: <201707131926.v6DJQ7U5036801@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: dim set sender to dim@FreeBSD.org using -f From: Dimitry Andric Date: Thu, 13 Jul 2017 19:26:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r320965 - in vendor/lld/dist: COFF ELF lib/ReaderWriter/MachO test test/COFF test/COFF/Inputs test/ELF test/ELF/Inputs test/ELF/invalid test/ELF/invalid/Inputs test/ELF/linkerscript tes... X-SVN-Group: vendor X-SVN-Commit-Author: dim X-SVN-Commit-Paths: in vendor/lld/dist: COFF ELF lib/ReaderWriter/MachO test test/COFF test/COFF/Inputs test/ELF test/ELF/Inputs test/ELF/invalid test/ELF/invalid/Inputs test/ELF/linkerscript test/ELF/lto X-SVN-Commit-Revision: 320965 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-vendor@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the vendor work area tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Jul 2017 19:26:10 -0000 Author: dim Date: Thu Jul 13 19:26:06 2017 New Revision: 320965 URL: https://svnweb.freebsd.org/changeset/base/320965 Log: Vendor import of lld trunk r307894: https://llvm.org/svn/llvm-project/lld/trunk@307894 Added: vendor/lld/dist/test/COFF/Inputs/library-arm64.lib (contents, props changed) vendor/lld/dist/test/COFF/Inputs/pdb-diff-cl.pdb (contents, props changed) vendor/lld/dist/test/COFF/Inputs/pdb-diff.cpp (contents, props changed) vendor/lld/dist/test/COFF/Inputs/pdb-diff.obj (contents, props changed) vendor/lld/dist/test/COFF/Inputs/pdb-scopes-a.yaml vendor/lld/dist/test/COFF/Inputs/pdb-scopes-b.yaml vendor/lld/dist/test/COFF/arm64-magic.yaml vendor/lld/dist/test/COFF/arm64-relocs-imports.test vendor/lld/dist/test/COFF/pdb-diff.test vendor/lld/dist/test/COFF/pdb-invalid-func-type.yaml vendor/lld/dist/test/COFF/pdb-linker-module.test vendor/lld/dist/test/COFF/pdb-scopes.test vendor/lld/dist/test/ELF/Inputs/gnu-ifunc-dso.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/symver-archive1.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/symver-archive2.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/version-script-no-warn2.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/version-script-weak.s (contents, props changed) vendor/lld/dist/test/ELF/Inputs/wrap-dynamic-undef.s (contents, props changed) vendor/lld/dist/test/ELF/duplicated-synthetic-sym.s (contents, props changed) vendor/lld/dist/test/ELF/gnu-ifunc-dso.s (contents, props changed) vendor/lld/dist/test/ELF/invalid/invalid-debug-relocations.test vendor/lld/dist/test/ELF/linkerscript/non-alloc-segment.s (contents, props changed) vendor/lld/dist/test/ELF/linkerscript/unused-synthetic.s (contents, props changed) vendor/lld/dist/test/ELF/symver-archive.s (contents, props changed) vendor/lld/dist/test/ELF/version-script-no-warn2.s (contents, props changed) vendor/lld/dist/test/ELF/version-script-symver2.s (contents, props changed) vendor/lld/dist/test/ELF/version-script-undef-version.s (contents, props changed) vendor/lld/dist/test/ELF/version-script-weak.s (contents, props changed) vendor/lld/dist/test/ELF/wrap-dynamic-undef.s (contents, props changed) Deleted: vendor/lld/dist/test/ELF/invalid/Inputs/invalid-relocation-x64.elf Modified: vendor/lld/dist/COFF/Chunks.cpp vendor/lld/dist/COFF/Chunks.h vendor/lld/dist/COFF/Config.h vendor/lld/dist/COFF/Driver.cpp vendor/lld/dist/COFF/DriverUtils.cpp vendor/lld/dist/COFF/Error.cpp vendor/lld/dist/COFF/Error.h vendor/lld/dist/COFF/InputFiles.cpp vendor/lld/dist/COFF/PDB.cpp vendor/lld/dist/COFF/PDB.h vendor/lld/dist/COFF/Symbols.cpp vendor/lld/dist/COFF/Writer.cpp vendor/lld/dist/ELF/Config.h vendor/lld/dist/ELF/Driver.cpp vendor/lld/dist/ELF/Error.cpp vendor/lld/dist/ELF/Error.h vendor/lld/dist/ELF/Filesystem.cpp vendor/lld/dist/ELF/GdbIndex.h vendor/lld/dist/ELF/InputFiles.cpp vendor/lld/dist/ELF/InputSection.cpp vendor/lld/dist/ELF/LinkerScript.cpp vendor/lld/dist/ELF/LinkerScript.h vendor/lld/dist/ELF/OutputSections.cpp vendor/lld/dist/ELF/OutputSections.h vendor/lld/dist/ELF/Relocations.cpp vendor/lld/dist/ELF/Relocations.h vendor/lld/dist/ELF/ScriptParser.cpp vendor/lld/dist/ELF/SymbolTable.cpp vendor/lld/dist/ELF/Symbols.cpp vendor/lld/dist/ELF/Symbols.h vendor/lld/dist/ELF/SyntheticSections.cpp vendor/lld/dist/ELF/SyntheticSections.h vendor/lld/dist/ELF/Thunks.cpp vendor/lld/dist/ELF/Thunks.h vendor/lld/dist/ELF/Writer.cpp vendor/lld/dist/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp vendor/lld/dist/test/COFF/combined-resources.test vendor/lld/dist/test/COFF/pdb-comdat.test vendor/lld/dist/test/COFF/pdb-lib.s vendor/lld/dist/test/COFF/pdb-none.test vendor/lld/dist/test/COFF/pdb-source-lines.test vendor/lld/dist/test/COFF/pdb-symbol-types.yaml vendor/lld/dist/test/COFF/pdb.test vendor/lld/dist/test/ELF/arm-mov-relocs.s vendor/lld/dist/test/ELF/copy-in-shared.s vendor/lld/dist/test/ELF/defsym.s vendor/lld/dist/test/ELF/invalid/invalid-relocation-x64.test vendor/lld/dist/test/ELF/linkerscript/locationcountererr2.s vendor/lld/dist/test/ELF/linkerscript/out-of-order.s vendor/lld/dist/test/ELF/lto/defsym.ll vendor/lld/dist/test/ELF/lto/wrap-1.ll vendor/lld/dist/test/ELF/lto/wrap-2.ll vendor/lld/dist/test/ELF/version-script-symver.s vendor/lld/dist/test/ELF/wrap.s vendor/lld/dist/test/lit.cfg Modified: vendor/lld/dist/COFF/Chunks.cpp ============================================================================== --- vendor/lld/dist/COFF/Chunks.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Chunks.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -52,6 +52,7 @@ static void add16(uint8_t *P, int16_t V) { write16le(P static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); } static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); } +static void or32(uint8_t *P, uint32_t V) { write32le(P, read32le(P) | V); } static void applySecRel(const SectionChunk *Sec, uint8_t *Off, OutputSection *OS, uint64_t S) { @@ -166,6 +167,41 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t } } +static void applyArm64Addr(uint8_t *Off, uint64_t Imm) { + uint32_t ImmLo = (Imm & 0x3) << 29; + uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; + uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); + write32le(Off, (read32le(Off) & ~Mask) | ImmLo | ImmHi); +} + +// Update the immediate field in a AARCH64 ldr, str, and add instruction. +static void applyArm64Imm(uint8_t *Off, uint64_t Imm) { + uint32_t Orig = read32le(Off); + Imm += (Orig >> 10) & 0xFFF; + Orig &= ~(0xFFF << 10); + write32le(Off, Orig | ((Imm & 0xFFF) << 10)); +} + +static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) { + int Size = read32le(Off) >> 30; + Imm >>= Size; + applyArm64Imm(Off, Imm); +} + +void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, + uint64_t S, uint64_t P) const { + switch (Type) { + case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, (S >> 12) - (P >> 12)); break; + case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff); break; + case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break; + case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break; + case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break; + case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break; + default: + fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); + } +} + void SectionChunk::writeTo(uint8_t *Buf) const { if (!hasData()) return; @@ -210,6 +246,9 @@ void SectionChunk::writeTo(uint8_t *Buf) const { case ARMNT: applyRelARM(Off, Rel.Type, OS, S, P); break; + case ARM64: + applyRelARM64(Off, Rel.Type, OS, S, P); + break; default: llvm_unreachable("unknown machine type"); } @@ -236,6 +275,10 @@ static uint8_t getBaserelType(const coff_relocation &R if (Rel.Type == IMAGE_REL_ARM_MOV32T) return IMAGE_REL_BASED_ARM_MOV32T; return IMAGE_REL_BASED_ABSOLUTE; + case ARM64: + if (Rel.Type == IMAGE_REL_ARM64_ADDR64) + return IMAGE_REL_BASED_DIR64; + return IMAGE_REL_BASED_ABSOLUTE; default: llvm_unreachable("unknown machine type"); } @@ -343,6 +386,14 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM)); // Fix mov.w and mov.t operands. applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase); +} + +void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { + int64_t PageOff = (ImpSymbol->getRVA() >> 12) - (RVA >> 12); + int64_t Off = ImpSymbol->getRVA() & 0xfff; + memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64)); + applyArm64Addr(Buf + OutputSectionOff, PageOff); + applyArm64Ldr(Buf + OutputSectionOff + 4, Off); } void LocalImportChunk::getBaserels(std::vector *Res) { Modified: vendor/lld/dist/COFF/Chunks.h ============================================================================== --- vendor/lld/dist/COFF/Chunks.h Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Chunks.h Thu Jul 13 19:26:06 2017 (r320965) @@ -151,6 +151,8 @@ class SectionChunk : public Chunk { (public) uint64_t P) const; void applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, uint64_t P) const; + void applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, + uint64_t P) const; // Called if the garbage collector decides to not include this chunk // in a final output. It's supposed to print out a log message to stdout. @@ -264,6 +266,12 @@ static const uint8_t ImportThunkARM[] = { 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip] }; +static const uint8_t ImportThunkARM64[] = { + 0x10, 0x00, 0x00, 0x90, // adrp x16, #0 + 0x10, 0x02, 0x40, 0xf9, // ldr x16, [x16] + 0x00, 0x02, 0x1f, 0xd6, // br x16 +}; + // Windows-specific. // A chunk for DLL import jump table entry. In a final output, it's // contents will be a JMP instruction to some __imp_ symbol. @@ -293,6 +301,16 @@ class ImportThunkChunkARM : public Chunk { (public) explicit ImportThunkChunkARM(Defined *S) : ImpSymbol(S) {} size_t getSize() const override { return sizeof(ImportThunkARM); } void getBaserels(std::vector *Res) override; + void writeTo(uint8_t *Buf) const override; + +private: + Defined *ImpSymbol; +}; + +class ImportThunkChunkARM64 : public Chunk { +public: + explicit ImportThunkChunkARM64(Defined *S) : ImpSymbol(S) {} + size_t getSize() const override { return sizeof(ImportThunkARM64); } void writeTo(uint8_t *Buf) const override; private: Modified: vendor/lld/dist/COFF/Config.h ============================================================================== --- vendor/lld/dist/COFF/Config.h Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Config.h Thu Jul 13 19:26:06 2017 (r320965) @@ -31,6 +31,7 @@ class SymbolBody; // Short aliases. static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64; +static const auto ARM64 = llvm::COFF::IMAGE_FILE_MACHINE_ARM64; static const auto ARMNT = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT; static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386; @@ -73,7 +74,7 @@ enum class DebugType { // Global configuration. struct Configuration { enum ManifestKind { SideBySide, Embed, No }; - bool is64() { return Machine == AMD64; } + bool is64() { return Machine == AMD64 || Machine == ARM64; } llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN; bool Verbose = false; @@ -91,6 +92,7 @@ struct Configuration { bool WriteSymtab = true; unsigned DebugTypes = static_cast(DebugType::None); llvm::SmallString<128> PDBPath; + std::vector Argv; // Symbols in this set are considered as live by the garbage collector. std::set GCRoot; Modified: vendor/lld/dist/COFF/Driver.cpp ============================================================================== --- vendor/lld/dist/COFF/Driver.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Driver.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -55,8 +55,8 @@ std::vector SpecificAllocBase::In bool link(ArrayRef Args, raw_ostream &Diag) { ErrorCount = 0; ErrorOS = &Diag; - Argv0 = Args[0]; Config = make(); + Config->Argv = {Args.begin(), Args.end()}; Config->ColorDiagnostics = (ErrorOS == &llvm::errs() && Process::StandardErrHasColors()); Driver = make(); Modified: vendor/lld/dist/COFF/DriverUtils.cpp ============================================================================== --- vendor/lld/dist/COFF/DriverUtils.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/DriverUtils.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -85,6 +85,7 @@ MachineTypes getMachineType(StringRef S) { .Cases("x64", "amd64", AMD64) .Cases("x86", "i386", I386) .Case("arm", ARMNT) + .Case("arm64", ARM64) .Default(IMAGE_FILE_MACHINE_UNKNOWN); if (MT != IMAGE_FILE_MACHINE_UNKNOWN) return MT; @@ -95,6 +96,8 @@ StringRef machineToStr(MachineTypes MT) { switch (MT) { case ARMNT: return "arm"; + case ARM64: + return "arm64"; case AMD64: return "x64"; case I386: @@ -378,13 +381,11 @@ static std::string createManifestXml() { static std::unique_ptr createMemoryBufferForManifestRes(size_t ManifestSize) { - size_t ResSize = alignTo(object::WIN_RES_MAGIC_SIZE + - object::WIN_RES_NULL_ENTRY_SIZE + - sizeof(object::WinResHeaderPrefix) + - sizeof(object::WinResIDs) + - sizeof(object::WinResHeaderSuffix) + - ManifestSize, - object::WIN_RES_DATA_ALIGNMENT); + size_t ResSize = alignTo( + object::WIN_RES_MAGIC_SIZE + object::WIN_RES_NULL_ENTRY_SIZE + + sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) + + sizeof(object::WinResHeaderSuffix) + ManifestSize, + object::WIN_RES_DATA_ALIGNMENT); return MemoryBuffer::getNewMemBuffer(ResSize); } Modified: vendor/lld/dist/COFF/Error.cpp ============================================================================== --- vendor/lld/dist/COFF/Error.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Error.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -29,7 +29,6 @@ namespace lld { static std::mutex Mu; namespace coff { -StringRef Argv0; uint64_t ErrorCount; raw_ostream *ErrorOS; @@ -45,7 +44,7 @@ static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) { } static void print(StringRef S, raw_ostream::Colors C) { - *ErrorOS << Argv0 + ": "; + *ErrorOS << Config->Argv[0] << ": "; if (Config->ColorDiagnostics) { ErrorOS->changeColor(C, true); *ErrorOS << S; @@ -58,7 +57,7 @@ static void print(StringRef S, raw_ostream::Colors C) void log(const Twine &Msg) { if (Config->Verbose) { std::lock_guard Lock(Mu); - outs() << Argv0 << ": " << Msg << "\n"; + outs() << Config->Argv[0] << ": " << Msg << "\n"; outs().flush(); } } Modified: vendor/lld/dist/COFF/Error.h ============================================================================== --- vendor/lld/dist/COFF/Error.h Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Error.h Thu Jul 13 19:26:06 2017 (r320965) @@ -18,7 +18,6 @@ namespace coff { extern uint64_t ErrorCount; extern llvm::raw_ostream *ErrorOS; -extern llvm::StringRef Argv0; void log(const Twine &Msg); void message(const Twine &Msg); Modified: vendor/lld/dist/COFF/InputFiles.cpp ============================================================================== --- vendor/lld/dist/COFF/InputFiles.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/InputFiles.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -380,6 +380,8 @@ MachineTypes BitcodeFile::getMachineType() { return I386; case Triple::arm: return ARMNT; + case Triple::aarch64: + return ARM64; default: return IMAGE_FILE_MACHINE_UNKNOWN; } Modified: vendor/lld/dist/COFF/PDB.cpp ============================================================================== --- vendor/lld/dist/COFF/PDB.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/PDB.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -18,19 +18,20 @@ #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" @@ -124,26 +125,25 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef Contents, ArrayRef TypeIndexMap, ArrayRef TypeRefs) { for (const TiReference &Ref : TypeRefs) { unsigned ByteSize = Ref.Count * sizeof(TypeIndex); - if (Contents.size() < Ref.Offset + ByteSize) { - log("ignoring short symbol record"); - return false; - } + if (Contents.size() < Ref.Offset + ByteSize) + fatal("symbol record too short"); MutableArrayRef TIs( reinterpret_cast(Contents.data() + Ref.Offset), Ref.Count); - for (TypeIndex &TI : TIs) + for (TypeIndex &TI : TIs) { if (!remapTypeIndex(TI, TypeIndexMap)) { + TI = TypeIndex(SimpleTypeKind::NotTranslated); log("ignoring symbol record in " + File->getName() + " with bad type index 0x" + utohexstr(TI.getIndex())); - return false; + continue; } + } } - return true; } /// MSVC translates S_PROC_ID_END to S_END. @@ -176,6 +176,70 @@ static MutableArrayRef copySymbolForPdb(const return NewData; } +/// Return true if this symbol opens a scope. This implies that the symbol has +/// "parent" and "end" fields, which contain the offset of the S_END or +/// S_INLINESITE_END record. +static bool symbolOpensScope(SymbolKind Kind) { + switch (Kind) { + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + case SymbolKind::S_LPROC32_ID: + case SymbolKind::S_GPROC32_ID: + case SymbolKind::S_BLOCK32: + case SymbolKind::S_SEPCODE: + case SymbolKind::S_THUNK32: + case SymbolKind::S_INLINESITE: + case SymbolKind::S_INLINESITE2: + return true; + default: + break; + } + return false; +} + +static bool symbolEndsScope(SymbolKind Kind) { + switch (Kind) { + case SymbolKind::S_END: + case SymbolKind::S_PROC_ID_END: + case SymbolKind::S_INLINESITE_END: + return true; + default: + break; + } + return false; +} + +struct ScopeRecord { + ulittle32_t PtrParent; + ulittle32_t PtrEnd; +}; + +struct SymbolScope { + ScopeRecord *OpeningRecord; + uint32_t ScopeOffset; +}; + +static void scopeStackOpen(SmallVectorImpl &Stack, + uint32_t CurOffset, CVSymbol &Sym) { + assert(symbolOpensScope(Sym.kind())); + SymbolScope S; + S.ScopeOffset = CurOffset; + S.OpeningRecord = const_cast( + reinterpret_cast(Sym.content().data())); + S.OpeningRecord->PtrParent = Stack.empty() ? 0 : Stack.back().ScopeOffset; + Stack.push_back(S); +} + +static void scopeStackClose(SmallVectorImpl &Stack, + uint32_t CurOffset, ObjectFile *File) { + if (Stack.empty()) { + warn("symbol scopes are not balanced in " + File->getName()); + return; + } + SymbolScope S = Stack.pop_back_val(); + S.OpeningRecord->PtrEnd = CurOffset; +} + static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, ArrayRef TypeIndexMap, BinaryStreamRef SymData) { @@ -184,6 +248,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc CVSymbolArray Syms; BinaryStreamReader Reader(SymData); ExitOnErr(Reader.readArray(Syms, Reader.getLength())); + SmallVector Scopes; for (const CVSymbol &Sym : Syms) { // Discover type index references in the record. Skip it if we don't know // where they are. @@ -199,14 +264,17 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc // Re-map all the type index references. MutableArrayRef Contents = NewData.drop_front(sizeof(RecordPrefix)); - if (!remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs)) - continue; + remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs); - // FIXME: Fill in "Parent" and "End" fields by maintaining a stack of - // scopes. + // Fill in "Parent" and "End" fields by maintaining a stack of scopes. + CVSymbol NewSym(Sym.kind(), NewData); + if (symbolOpensScope(Sym.kind())) + scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(), NewSym); + else if (symbolEndsScope(Sym.kind())) + scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File); // Add the symbol to the module. - File->ModuleDBI->addSymbol(CVSymbol(Sym.kind(), NewData)); + File->ModuleDBI->addSymbol(NewSym); } } @@ -246,7 +314,9 @@ static void addObjectsToPDB(BumpPtrAllocator &Alloc, S bool InArchive = !File->ParentName.empty(); SmallString<128> Path = InArchive ? File->ParentName : File->getName(); sys::fs::make_absolute(Path); + sys::path::native(Path, llvm::sys::path::Style::windows); StringRef Name = InArchive ? File->getName() : StringRef(Path); + File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); File->ModuleDBI->setObjFileName(Path); @@ -325,9 +395,52 @@ static void addObjectsToPDB(BumpPtrAllocator &Alloc, S addTypeInfo(Builder.getIpiBuilder(), IDTable); } +static void addLinkerModuleSymbols(StringRef Path, + pdb::DbiModuleDescriptorBuilder &Mod, + BumpPtrAllocator &Allocator) { + codeview::SymbolSerializer Serializer(Allocator, CodeViewContainer::Pdb); + codeview::ObjNameSym ONS(SymbolRecordKind::ObjNameSym); + codeview::Compile3Sym CS(SymbolRecordKind::Compile3Sym); + codeview::EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); + + ONS.Name = "* Linker *"; + ONS.Signature = 0; + + CS.Machine = Config->is64() ? CPUType::X64 : CPUType::Intel80386; + CS.Flags = CompileSym3Flags::None; + CS.VersionBackendBuild = 0; + CS.VersionBackendMajor = 0; + CS.VersionBackendMinor = 0; + CS.VersionBackendQFE = 0; + CS.VersionFrontendBuild = 0; + CS.VersionFrontendMajor = 0; + CS.VersionFrontendMinor = 0; + CS.VersionFrontendQFE = 0; + CS.Version = "LLVM Linker"; + CS.setLanguage(SourceLanguage::Link); + + ArrayRef Args = makeArrayRef(Config->Argv).drop_front(); + std::string ArgStr = llvm::join(Args, " "); + EBS.Fields.push_back("cwd"); + SmallString<64> cwd; + llvm::sys::fs::current_path(cwd); + EBS.Fields.push_back(cwd); + EBS.Fields.push_back("exe"); + EBS.Fields.push_back(Config->Argv[0]); + EBS.Fields.push_back("pdb"); + EBS.Fields.push_back(Path); + EBS.Fields.push_back("cmd"); + EBS.Fields.push_back(ArgStr); + Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + ONS, Allocator, CodeViewContainer::Pdb)); + Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + CS, Allocator, CodeViewContainer::Pdb)); + Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + EBS, Allocator, CodeViewContainer::Pdb)); +} + // Creates a PDB file. -void coff::createPDB(StringRef Path, SymbolTable *Symtab, - ArrayRef SectionTable, +void coff::createPDB(SymbolTable *Symtab, ArrayRef SectionTable, const llvm::codeview::DebugInfo *DI) { BumpPtrAllocator Alloc; pdb::PDBFileBuilder Builder(Alloc); @@ -342,22 +455,37 @@ void coff::createPDB(StringRef Path, SymbolTable *Symt auto &InfoBuilder = Builder.getInfoBuilder(); InfoBuilder.setAge(DI ? DI->PDB70.Age : 0); + llvm::SmallString<128> NativePath(Config->PDBPath.begin(), + Config->PDBPath.end()); + llvm::sys::fs::make_absolute(NativePath); + llvm::sys::path::native(NativePath, llvm::sys::path::Style::windows); + pdb::PDB_UniqueId uuid{}; if (DI) memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid)); InfoBuilder.setGuid(uuid); - // Should be the current time, but set 0 for reproducibilty. - InfoBuilder.setSignature(0); + InfoBuilder.setSignature(time(nullptr)); InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); - // Add an empty DPI stream. + // Add an empty DBI stream. pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); - DbiBuilder.setVersionHeader(pdb::PdbDbiV110); + DbiBuilder.setVersionHeader(pdb::PdbDbiV70); + ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {})); + // It's not entirely clear what this is, but the * Linker * module uses it. + uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); + TypeTableBuilder TypeTable(BAlloc); TypeTableBuilder IDTable(BAlloc); addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable); + // Add public and symbol records stream. + + // For now we don't actually write any thing useful to the publics stream, but + // the act of "getting" it also creates it lazily so that we write an empty + // stream. + (void)Builder.getPublicsBuilder(); + // Add Section Contributions. addSectionContribs(Symtab, DbiBuilder); @@ -369,12 +497,14 @@ void coff::createPDB(StringRef Path, SymbolTable *Symt pdb::DbiStreamBuilder::createSectionMap(Sections); DbiBuilder.setSectionMap(SectionMap); - ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); + auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); + LinkerModule.setPdbFilePathNI(PdbFilePathNI); + addLinkerModuleSymbols(NativePath, LinkerModule, Alloc); // Add COFF section header stream. ExitOnErr( DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); // Write to a file. - ExitOnErr(Builder.commit(Path)); + ExitOnErr(Builder.commit(Config->PDBPath)); } Modified: vendor/lld/dist/COFF/PDB.h ============================================================================== --- vendor/lld/dist/COFF/PDB.h Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/PDB.h Thu Jul 13 19:26:06 2017 (r320965) @@ -23,8 +23,7 @@ namespace lld { namespace coff { class SymbolTable; -void createPDB(llvm::StringRef Path, SymbolTable *Symtab, - llvm::ArrayRef SectionTable, +void createPDB(SymbolTable *Symtab, llvm::ArrayRef SectionTable, const llvm::codeview::DebugInfo *DI); } } Modified: vendor/lld/dist/COFF/Symbols.cpp ============================================================================== --- vendor/lld/dist/COFF/Symbols.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Symbols.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -68,6 +68,8 @@ static Chunk *makeImportThunk(DefinedImportData *S, ui return make(S); if (Machine == I386) return make(S); + if (Machine == ARM64) + return make(S); assert(Machine == ARMNT); return make(S); } Modified: vendor/lld/dist/COFF/Writer.cpp ============================================================================== --- vendor/lld/dist/COFF/Writer.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/COFF/Writer.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -239,7 +239,7 @@ void Writer::run() { const llvm::codeview::DebugInfo *DI = nullptr; if (Config->DebugTypes & static_cast(coff::DebugType::CV)) DI = BuildId->DI; - createPDB(Config->PDBPath, Symtab, SectionTable, DI); + createPDB(Symtab, SectionTable, DI); } writeMapFile(OutputSections); Modified: vendor/lld/dist/ELF/Config.h ============================================================================== --- vendor/lld/dist/ELF/Config.h Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/Config.h Thu Jul 13 19:26:06 2017 (r320965) @@ -97,6 +97,7 @@ struct Configuration { llvm::StringRef ThinLTOCacheDir; std::string Rpath; std::vector VersionDefinitions; + std::vector Argv; std::vector AuxiliaryList; std::vector SearchPaths; std::vector SymbolOrderingFile; Modified: vendor/lld/dist/ELF/Driver.cpp ============================================================================== --- vendor/lld/dist/ELF/Driver.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/Driver.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -74,13 +74,13 @@ bool elf::link(ArrayRef Args, bool CanEx raw_ostream &Error) { ErrorCount = 0; ErrorOS = &Error; - Argv0 = Args[0]; InputSections.clear(); Tar = nullptr; Config = make(); Driver = make(); Script = make(); + Config->Argv = {Args.begin(), Args.end()}; Driver->main(Args, CanExitEarly); freeArena(); Modified: vendor/lld/dist/ELF/Error.cpp ============================================================================== --- vendor/lld/dist/ELF/Error.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/Error.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -27,7 +27,6 @@ using namespace lld::elf; uint64_t elf::ErrorCount; raw_ostream *elf::ErrorOS; -StringRef elf::Argv0; // The functions defined in this file can be called from multiple threads, // but outs() or errs() are not thread-safe. We protect them using a mutex. @@ -46,7 +45,7 @@ static void newline(const Twine &Msg) { } static void print(StringRef S, raw_ostream::Colors C) { - *ErrorOS << Argv0 + ": "; + *ErrorOS << Config->Argv[0] << ": "; if (Config->ColorDiagnostics) { ErrorOS->changeColor(C, true); *ErrorOS << S; @@ -59,7 +58,7 @@ static void print(StringRef S, raw_ostream::Colors C) void elf::log(const Twine &Msg) { if (Config->Verbose) { std::lock_guard Lock(Mu); - outs() << Argv0 << ": " << Msg << "\n"; + outs() << Config->Argv[0] << ": " << Msg << "\n"; outs().flush(); } } Modified: vendor/lld/dist/ELF/Error.h ============================================================================== --- vendor/lld/dist/ELF/Error.h Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/Error.h Thu Jul 13 19:26:06 2017 (r320965) @@ -37,7 +37,6 @@ namespace elf { extern uint64_t ErrorCount; extern llvm::raw_ostream *ErrorOS; -extern llvm::StringRef Argv0; void log(const Twine &Msg); void message(const Twine &Msg); Modified: vendor/lld/dist/ELF/Filesystem.cpp ============================================================================== --- vendor/lld/dist/ELF/Filesystem.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/Filesystem.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -38,7 +38,8 @@ using namespace lld::elf; // This function spawns a background thread to call unlink. // The calling thread returns almost immediately. void elf::unlinkAsync(StringRef Path) { - if (!Config->Threads || !sys::fs::exists(Config->OutputFile)) + if (!Config->Threads || !sys::fs::exists(Config->OutputFile) || + !sys::fs::is_regular_file(Config->OutputFile)) return; // First, rename Path to avoid race condition. We cannot remove Modified: vendor/lld/dist/ELF/GdbIndex.h ============================================================================== --- vendor/lld/dist/ELF/GdbIndex.h Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/GdbIndex.h Thu Jul 13 19:26:06 2017 (r320965) @@ -45,6 +45,7 @@ struct NameTypeEntry { // debug information performed. That information futher used // for filling gdb index section areas. struct GdbIndexChunk { + InputSection *DebugInfoSec; std::vector AddressArea; std::vector CompilationUnits; std::vector NamesAndTypes; Modified: vendor/lld/dist/ELF/InputFiles.cpp ============================================================================== --- vendor/lld/dist/ELF/InputFiles.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/InputFiles.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -45,13 +45,10 @@ namespace { // LLVM DWARF parser will not be able to parse .debug_line correctly, unless // we assign each section some unique address. This callback method assigns // each section an address equal to its offset in ELF object file. -class ObjectInfo : public LoadedObjectInfo { +class ObjectInfo : public LoadedObjectInfoHelper { public: uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override { return static_cast(Sec).getOffset(); - } - std::unique_ptr clone() const override { - return std::unique_ptr(); } }; } Modified: vendor/lld/dist/ELF/InputSection.cpp ============================================================================== --- vendor/lld/dist/ELF/InputSection.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/InputSection.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -276,7 +276,9 @@ template std::string InputSectionBase::ge template std::string InputSectionBase::getObjMsg(uint64_t Off) { // Synthetic sections don't have input files. elf::ObjectFile *File = getFile(); - std::string Filename = File ? File->getName() : "(internal)"; + if (!File) + return ("(internal):(" + Name + "+0x" + utohexstr(Off) + ")").str(); + std::string Filename = File->getName(); std::string Archive; if (!File->ArchiveName.empty()) @@ -466,7 +468,7 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint static uint64_t getARMStaticBase(const SymbolBody &Body) { OutputSection *OS = Body.getOutputSection(); if (!OS || !OS->FirstInPtLoad) - fatal("SBREL relocation to " + Body.getName() + " without static base\n"); + fatal("SBREL relocation to " + Body.getName() + " without static base"); return OS->FirstInPtLoad->Addr; } Modified: vendor/lld/dist/ELF/LinkerScript.cpp ============================================================================== --- vendor/lld/dist/ELF/LinkerScript.cpp Thu Jul 13 19:26:02 2017 (r320964) +++ vendor/lld/dist/ELF/LinkerScript.cpp Thu Jul 13 19:26:06 2017 (r320965) @@ -111,17 +111,13 @@ LinkerScript::getOrCreateOutputSectionCommand(StringRe void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { uint64_t Val = E().getValue(); - if (Val < Dot) { - if (InSec) - error(Loc + ": unable to move location counter backward for: " + - CurOutSec->Name); - else - error(Loc + ": unable to move location counter backward"); - } + if (Val < Dot && InSec) + error(Loc + ": unable to move location counter backward for: " + + CurAddressState->OutSec->Name); Dot = Val; // Update to location counter means update to section size. if (InSec) - CurOutSec->Size = Dot - CurOutSec->Addr; + CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr; } // Sets value of a symbol. Two kinds of symbols are processed: synthetic @@ -373,7 +369,13 @@ void LinkerScript::processCommands(OutputSectionFactor // which will map to whatever the first actual section is. Aether = make("", 0, SHF_ALLOC); Aether->SectionIndex = 1; - CurOutSec = Aether; + auto State = make_unique(Opt); + // CurAddressState captures the local AddressState and makes it accessible + // deliberately. This is needed as there are some cases where we cannot just + // thread the current state through to a lambda function created by the + // script parser. + CurAddressState = State.get(); + CurAddressState->OutSec = Aether; Dot = 0; for (size_t I = 0; I < Opt.Commands.size(); ++I) { @@ -435,7 +437,7 @@ void LinkerScript::processCommands(OutputSectionFactor } } } - CurOutSec = nullptr; + CurAddressState = nullptr; } void LinkerScript::fabricateDefaultCommands() { @@ -481,20 +483,31 @@ void LinkerScript::fabricateDefaultCommands() { // Add sections that didn't match any sections command. void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { + unsigned NumCommands = Opt.Commands.size(); for (InputSectionBase *S : InputSections) { if (!S->Live || S->Parent) continue; StringRef Name = getOutputSectionName(S->Name); - auto I = std::find_if( - Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) { - if (auto *Cmd = dyn_cast(Base)) - return Cmd->Name == Name; - return false; - }); - if (I == Opt.Commands.end()) { + auto End = Opt.Commands.begin() + NumCommands; + auto I = std::find_if(Opt.Commands.begin(), End, [&](BaseCommand *Base) { + if (auto *Cmd = dyn_cast(Base)) + return Cmd->Name == Name; + return false; + }); + OutputSectionCommand *Cmd; + if (I == End) { Factory.addInputSec(S, Name); + OutputSection *Sec = S->getOutputSection(); + assert(Sec->SectionIndex == INT_MAX); + OutputSectionCommand *&CmdRef = SecToCommand[Sec]; + if (!CmdRef) { + CmdRef = createOutputSectionCommand(Sec->Name, ""); + CmdRef->Sec = Sec; + Opt.Commands.push_back(CmdRef); + } + Cmd = CmdRef; } else { - auto *Cmd = cast(*I); + Cmd = cast(*I); Factory.addInputSec(S, Name, Cmd->Sec); if (OutputSection *Sec = Cmd->Sec) { SecToCommand[Sec] = Cmd; @@ -502,21 +515,22 @@ void LinkerScript::addOrphanSections(OutputSectionFact assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index); Sec->SectionIndex = Index; } - auto *ISD = make(""); - ISD->Sections.push_back(cast(S)); - Cmd->Commands.push_back(ISD); } + auto *ISD = make(""); + ISD->Sections.push_back(cast(S)); + Cmd->Commands.push_back(ISD); } } uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) { - bool IsTbss = (CurOutSec->Flags & SHF_TLS) && CurOutSec->Type == SHT_NOBITS; - uint64_t Start = IsTbss ? Dot + ThreadBssOffset : Dot; + bool IsTbss = (CurAddressState->OutSec->Flags & SHF_TLS) && + CurAddressState->OutSec->Type == SHT_NOBITS; + uint64_t Start = IsTbss ? Dot + CurAddressState->ThreadBssOffset : Dot; Start = alignTo(Start, Align); uint64_t End = Start + Size; if (IsTbss) - ThreadBssOffset = End - Dot; + CurAddressState->ThreadBssOffset = End - Dot; else Dot = End; return End; @@ -524,40 +538,43 @@ uint64_t LinkerScript::advance(uint64_t Size, unsigned void LinkerScript::output(InputSection *S) { uint64_t Pos = advance(S->getSize(), S->Alignment); - S->OutSecOff = Pos - S->getSize() - CurOutSec->Addr; + S->OutSecOff = Pos - S->getSize() - CurAddressState->OutSec->Addr; // Update output section size after adding each section. This is so that // SIZEOF works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } - CurOutSec->Size = Pos - CurOutSec->Addr; + CurAddressState->OutSec->Size = Pos - CurAddressState->OutSec->Addr; // If there is a memory region associated with this input section, then // place the section in that region and update the region index. - if (CurMemRegion) { - CurMemRegion->Offset += CurOutSec->Size; - uint64_t CurSize = CurMemRegion->Offset - CurMemRegion->Origin; - if (CurSize > CurMemRegion->Length) { - uint64_t OverflowAmt = CurSize - CurMemRegion->Length; - error("section '" + CurOutSec->Name + "' will not fit in region '" + - CurMemRegion->Name + "': overflowed by " + Twine(OverflowAmt) + - " bytes"); + if (CurAddressState->MemRegion) { + uint64_t &CurOffset = + CurAddressState->MemRegionOffset[CurAddressState->MemRegion]; + CurOffset += CurAddressState->OutSec->Size; + uint64_t CurSize = CurOffset - CurAddressState->MemRegion->Origin; + if (CurSize > CurAddressState->MemRegion->Length) { + uint64_t OverflowAmt = CurSize - CurAddressState->MemRegion->Length; + error("section '" + CurAddressState->OutSec->Name + + "' will not fit in region '" + CurAddressState->MemRegion->Name + + "': overflowed by " + Twine(OverflowAmt) + " bytes"); } } } void LinkerScript::switchTo(OutputSection *Sec) { - if (CurOutSec == Sec) + if (CurAddressState->OutSec == Sec) return; - CurOutSec = Sec; - CurOutSec->Addr = advance(0, CurOutSec->Alignment); + CurAddressState->OutSec = Sec; + CurAddressState->OutSec->Addr = + advance(0, CurAddressState->OutSec->Alignment); // If neither AT nor AT> is specified for an allocatable section, the linker // will set the LMA such that the difference between VMA and LMA for the // section is the same as the preceding output section in the same region // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html - if (LMAOffset) - CurOutSec->LMAOffset = LMAOffset(); + if (CurAddressState->LMAOffset) + CurAddressState->OutSec->LMAOffset = CurAddressState->LMAOffset(); } void LinkerScript::process(BaseCommand &Base) { @@ -569,9 +586,9 @@ void LinkerScript::process(BaseCommand &Base) { // Handle BYTE(), SHORT(), LONG(), or QUAD(). if (auto *Cmd = dyn_cast(&Base)) { - Cmd->Offset = Dot - CurOutSec->Addr; + Cmd->Offset = Dot - CurAddressState->OutSec->Addr; Dot += Cmd->Size; - CurOutSec->Size = Dot - CurOutSec->Addr; + CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr; return; } @@ -596,7 +613,7 @@ void LinkerScript::process(BaseCommand &Base) { if (!Sec->Live) continue; - assert(CurOutSec == Sec->getParent()); + assert(CurAddressState->OutSec == Sec->getParent()); output(Sec); } } @@ -649,17 +666,17 @@ void LinkerScript::assignOffsets(OutputSectionCommand if (Cmd->LMAExpr) { uint64_t D = Dot; - LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; }; + CurAddressState->LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; }; } - CurMemRegion = Cmd->MemRegion; - if (CurMemRegion) - Dot = CurMemRegion->Offset; + CurAddressState->MemRegion = Cmd->MemRegion; + if (CurAddressState->MemRegion) + Dot = CurAddressState->MemRegionOffset[CurAddressState->MemRegion]; switchTo(Sec); // We do not support custom layout for compressed debug sectons. // At this point we already know their size and have compressed content. - if (CurOutSec->Flags & SHF_COMPRESSED) + if (CurAddressState->OutSec->Flags & SHF_COMPRESSED) return; for (BaseCommand *C : Cmd->Commands) @@ -746,30 +763,20 @@ void LinkerScript::adjustSectionsAfterSorting() { if (!Cmd) continue; - if (Cmd->Phdrs.empty()) - Cmd->Phdrs = DefPhdrs; - else + if (Cmd->Phdrs.empty()) { + OutputSection *Sec = Cmd->Sec; + // To match the bfd linker script behaviour, only propagate program + // headers to sections that are allocated. + if (Sec && (Sec->Flags & SHF_ALLOC)) + Cmd->Phdrs = DefPhdrs; + } else { DefPhdrs = Cmd->Phdrs; + } } removeEmptyCommands(); } -void LinkerScript::createOrphanCommands() { - for (OutputSection *Sec : OutputSections) { - if (Sec->SectionIndex != INT_MAX) - continue; - OutputSectionCommand *Cmd = - createOutputSectionCommand(Sec->Name, ""); - Cmd->Sec = Sec; - SecToCommand[Sec] = Cmd; - auto *ISD = make(""); - ISD->Sections = Sec->Sections; - Cmd->Commands.push_back(ISD); - Opt.Commands.push_back(Cmd); - } -} - void LinkerScript::processNonSectionCommands() { for (BaseCommand *Base : Opt.Commands) { if (auto *Cmd = dyn_cast(Base)) @@ -779,22 +786,25 @@ void LinkerScript::processNonSectionCommands() { } } -static bool -allocateHeaders(std::vector &Phdrs, - ArrayRef OutputSectionCommands, - uint64_t Min) { - auto FirstPTLoad = - std::find_if(Phdrs.begin(), Phdrs.end(), - [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); +void LinkerScript::allocateHeaders(std::vector &Phdrs) { + uint64_t Min = std::numeric_limits::max(); + for (OutputSectionCommand *Cmd : OutputSectionCommands) { + OutputSection *Sec = Cmd->Sec; + if (Sec->Flags & SHF_ALLOC) + Min = std::min(Min, Sec->Addr); + } + + auto FirstPTLoad = llvm::find_if( + Phdrs, [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); if (FirstPTLoad == Phdrs.end()) - return false; + return; uint64_t HeaderSize = getHeaderSize(); if (HeaderSize <= Min || Script->hasPhdrsCommands()) { Min = alignDown(Min - HeaderSize, Config->MaxPageSize); Out::ElfHeader->Addr = Min; Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; - return true; + return; } assert(FirstPTLoad->First == Out::ElfHeader); @@ -817,17 +827,28 @@ allocateHeaders(std::vector &Phdrs, Phdrs.erase(FirstPTLoad); } - auto PhdrI = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) { - return E.p_type == PT_PHDR; - }); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***