Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Jul 2017 19:26:07 +0000 (UTC)
From:      Dimitry Andric <dim@FreeBSD.org>
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...
Message-ID:  <201707131926.v6DJQ7U5036801@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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<Baserel> *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<Baserel> *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<unsigned>(DebugType::None);
   llvm::SmallString<128> PDBPath;
+  std::vector<llvm::StringRef> Argv;
 
   // Symbols in this set are considered as live by the garbage collector.
   std::set<SymbolBody *> 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 *> SpecificAllocBase::In
 bool link(ArrayRef<const char *> Args, raw_ostream &Diag) {
   ErrorCount = 0;
   ErrorOS = &Diag;
-  Argv0 = Args[0];
   Config = make<Configuration>();
+  Config->Argv = {Args.begin(), Args.end()};
   Config->ColorDiagnostics =
       (ErrorOS == &llvm::errs() && Process::StandardErrHasColors());
   Driver = make<LinkerDriver>();

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<MemoryBuffer>
 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<std::mutex> 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<Typ
   return true;
 }
 
-static bool remapTypesInSymbolRecord(ObjectFile *File,
+static void remapTypesInSymbolRecord(ObjectFile *File,
                                      MutableArrayRef<uint8_t> Contents,
                                      ArrayRef<TypeIndex> TypeIndexMap,
                                      ArrayRef<TiReference> 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<TypeIndex> TIs(
         reinterpret_cast<TypeIndex *>(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<uint8_t> 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<SymbolScope> &Stack,
+                           uint32_t CurOffset, CVSymbol &Sym) {
+  assert(symbolOpensScope(Sym.kind()));
+  SymbolScope S;
+  S.ScopeOffset = CurOffset;
+  S.OpeningRecord = const_cast<ScopeRecord *>(
+      reinterpret_cast<const ScopeRecord *>(Sym.content().data()));
+  S.OpeningRecord->PtrParent = Stack.empty() ? 0 : Stack.back().ScopeOffset;
+  Stack.push_back(S);
+}
+
+static void scopeStackClose(SmallVectorImpl<SymbolScope> &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<TypeIndex> TypeIndexMap,
                                BinaryStreamRef SymData) {
@@ -184,6 +248,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc
   CVSymbolArray Syms;
   BinaryStreamReader Reader(SymData);
   ExitOnErr(Reader.readArray(Syms, Reader.getLength()));
+  SmallVector<SymbolScope, 4> 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<uint8_t> 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<StringRef> 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<uint8_t> SectionTable,
+void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> 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<uint8_t> SectionTable,
+void createPDB(SymbolTable *Symtab, llvm::ArrayRef<uint8_t> 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<ImportThunkChunkX64>(S);
   if (Machine == I386)
     return make<ImportThunkChunkX86>(S);
+  if (Machine == ARM64)
+    return make<ImportThunkChunkARM64>(S);
   assert(Machine == ARMNT);
   return make<ImportThunkChunkARM>(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<unsigned>(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<VersionDefinition> VersionDefinitions;
+  std::vector<llvm::StringRef> Argv;
   std::vector<llvm::StringRef> AuxiliaryList;
   std::vector<llvm::StringRef> SearchPaths;
   std::vector<llvm::StringRef> 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<const char *> Args, bool CanEx
                raw_ostream &Error) {
   ErrorCount = 0;
   ErrorOS = &Error;
-  Argv0 = Args[0];
   InputSections.clear();
   Tar = nullptr;
 
   Config = make<Configuration>();
   Driver = make<LinkerDriver>();
   Script = make<LinkerScript>();
+  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<std::mutex> 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<AddressEntry> AddressArea;
   std::vector<CompilationUnitEntry> CompilationUnits;
   std::vector<NameTypeEntry> 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<ObjectInfo> {
 public:
   uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override {
     return static_cast<const ELFSectionRef &>(Sec).getOffset();
-  }
-  std::unique_ptr<LoadedObjectInfo> clone() const override {
-    return std::unique_ptr<LoadedObjectInfo>();
   }
 };
 }

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 <class ELFT> std::string InputSectionBase::ge
 template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) {
   // Synthetic sections don't have input files.
   elf::ObjectFile<ELFT> *File = getFile<ELFT>();
-  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<OutputSection>("", 0, SHF_ALLOC);
   Aether->SectionIndex = 1;
-  CurOutSec = Aether;
+  auto State = make_unique<AddressState>(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<OutputSectionCommand>(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<OutputSectionCommand>(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, "<internal>");
+        CmdRef->Sec = Sec;
+        Opt.Commands.push_back(CmdRef);
+      }
+      Cmd = CmdRef;
     } else {
-      auto *Cmd = cast<OutputSectionCommand>(*I);
+      Cmd = cast<OutputSectionCommand>(*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<InputSectionDescription>("");
-      ISD->Sections.push_back(cast<InputSection>(S));
-      Cmd->Commands.push_back(ISD);
     }
+    auto *ISD = make<InputSectionDescription>("");
+    ISD->Sections.push_back(cast<InputSection>(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<BytesDataCommand>(&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, "<internal>");
-    Cmd->Sec = Sec;
-    SecToCommand[Sec] = Cmd;
-    auto *ISD = make<InputSectionDescription>("");
-    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<SymbolAssignment>(Base))
@@ -779,22 +786,25 @@ void LinkerScript::processNonSectionCommands() {
   }
 }
 
-static bool
-allocateHeaders(std::vector<PhdrEntry> &Phdrs,
-                ArrayRef<OutputSectionCommand *> 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<PhdrEntry> &Phdrs) {
+  uint64_t Min = std::numeric_limits<uint64_t>::max();
+  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
+    OutputSection *Sec = Cmd->Sec;
+    if (Sec->Flags & SHF_ALLOC)
+      Min = std::min<uint64_t>(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<PhdrEntry> &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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707131926.v6DJQ7U5036801>