Merge commit 500a98301c1b

- upstream svn@328902

Test: git diff 500a98301c1b == git diff dccbfb97022 84071b532ebf
Change-Id: I187317e286d2598489813a281482c62dec4326f5
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
index 6da121e..451e18a 100644
--- a/COFF/Chunks.cpp
+++ b/COFF/Chunks.cpp
@@ -571,5 +571,47 @@
   }
 }
 
+std::map<uint32_t, MergeChunk *> MergeChunk::Instances;
+
+MergeChunk::MergeChunk(uint32_t Alignment)
+    : Builder(StringTableBuilder::RAW, Alignment) {
+  this->Alignment = Alignment;
+}
+
+void MergeChunk::addSection(SectionChunk *C) {
+  auto *&MC = Instances[C->Alignment];
+  if (!MC)
+    MC = make<MergeChunk>(C->Alignment);
+  MC->Sections.push_back(C);
+}
+
+void MergeChunk::finalizeContents() {
+  for (SectionChunk *C : Sections)
+    if (C->isLive())
+      Builder.add(toStringRef(C->getContents()));
+  Builder.finalize();
+
+  for (SectionChunk *C : Sections) {
+    if (!C->isLive())
+      continue;
+    size_t Off = Builder.getOffset(toStringRef(C->getContents()));
+    C->setOutputSection(Out);
+    C->setRVA(RVA + Off);
+    C->OutputSectionOff = OutputSectionOff + Off;
+  }
+}
+
+uint32_t MergeChunk::getPermissions() const {
+  return IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA;
+}
+
+size_t MergeChunk::getSize() const {
+  return Builder.getSize();
+}
+
+void MergeChunk::writeTo(uint8_t *Buf) const {
+  Builder.write(Buf + OutputSectionOff);
+}
+
 } // namespace coff
 } // namespace lld
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
index b4b2299..b95869a 100644
--- a/COFF/Chunks.h
+++ b/COFF/Chunks.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
+#include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/COFF.h"
 #include <utility>
 #include <vector>
@@ -60,6 +61,10 @@
   // before calling this function.
   virtual void writeTo(uint8_t *Buf) const {}
 
+  // Called by the writer after an RVA is assigned, but before calling
+  // getSize().
+  virtual void finalizeContents() {}
+
   // The writer sets and uses the addresses.
   uint64_t getRVA() const { return RVA; }
   void setRVA(uint64_t V) { RVA = V; }
@@ -222,6 +227,33 @@
   uint32_t Class[2] = {0, 0};
 };
 
+// This class is used to implement an lld-specific feature (not implemented in
+// MSVC) that minimizes the output size by finding string literals sharing tail
+// parts and merging them.
+//
+// If string tail merging is enabled and a section is identified as containing a
+// string literal, it is added to a MergeChunk with an appropriate alignment.
+// The MergeChunk then tail merges the strings using the StringTableBuilder
+// class and assigns RVAs and section offsets to each of the member chunks based
+// on the offsets assigned by the StringTableBuilder.
+class MergeChunk : public Chunk {
+public:
+  MergeChunk(uint32_t Alignment);
+  static void addSection(SectionChunk *C);
+  void finalizeContents() override;
+
+  uint32_t getPermissions() const override;
+  StringRef getSectionName() const override { return ".rdata"; }
+  size_t getSize() const override;
+  void writeTo(uint8_t *Buf) const override;
+
+  static std::map<uint32_t, MergeChunk *> Instances;
+  std::vector<SectionChunk *> Sections;
+
+private:
+  llvm::StringTableBuilder Builder;
+};
+
 // A chunk for common symbols. Common chunks don't have actual data.
 class CommonChunk : public Chunk {
 public:
diff --git a/COFF/Config.h b/COFF/Config.h
index c3e9730..1a03a24 100644
--- a/COFF/Config.h
+++ b/COFF/Config.h
@@ -99,6 +99,7 @@
   bool DebugGHashes = false;
   bool ShowTiming = false;
   unsigned DebugTypes = static_cast<unsigned>(DebugType::None);
+  std::vector<std::string> NatvisFiles;
   llvm::SmallString<128> PDBPath;
   std::vector<llvm::StringRef> Argv;
 
@@ -187,8 +188,10 @@
   bool HighEntropyVA = false;
   bool AppContainer = false;
   bool MinGW = false;
+  bool WarnMissingOrderSymbol = true;
   bool WarnLocallyDefinedImported = true;
   bool Incremental = true;
+  bool KillAt = false;
 };
 
 extern Configuration *Config;
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index e493bde..02b2208 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -61,7 +61,7 @@
   errorHandler().ColorDiagnostics = Diag.has_colors();
   errorHandler().ErrorLimitExceededMsg =
       "too many errors emitted, stopping now"
-      " (use /ERRORLIMIT:0 to see all errors)";
+      " (use /errorlimit:0 to see all errors)";
   errorHandler().ExitEarly = CanExitEarly;
   Config = make<Configuration>();
   Config->Argv = {Args.begin(), Args.end()};
@@ -804,8 +804,10 @@
     if (Config->Machine == I386 && !isDecorated(S))
       S = "_" + S;
 
-    if (Set.count(S) == 0)
-      warn("/order:" + Arg + ": missing symbol: " + S);
+    if (Set.count(S) == 0) {
+      if (Config->WarnMissingOrderSymbol)
+        warn("/order:" + Arg + ": missing symbol: " + S + " [LNK4037]");
+    }
     else
       Config->Order[S] = INT_MIN + Config->Order.size();
   }
@@ -899,7 +901,9 @@
 
   // Handle /ignore
   for (auto *Arg : Args.filtered(OPT_ignore)) {
-    if (StringRef(Arg->getValue()) == "4217")
+    if (StringRef(Arg->getValue()) == "4037")
+      Config->WarnMissingOrderSymbol = false;
+    else if (StringRef(Arg->getValue()) == "4217")
       Config->WarnLocallyDefinedImported = false;
     // Other warning numbers are ignored.
   }
@@ -929,9 +933,12 @@
 
   // Handle /pdb
   bool ShouldCreatePDB = Args.hasArg(OPT_debug, OPT_debug_ghash);
-  if (ShouldCreatePDB)
+  if (ShouldCreatePDB) {
     if (auto *Arg = Args.getLastArg(OPT_pdb))
       Config->PDBPath = Arg->getValue();
+    if (Args.hasArg(OPT_natvis))
+      Config->NatvisFiles = Args.getAllArgValues(OPT_natvis);
+  }
 
   // Handle /noentry
   if (Args.hasArg(OPT_noentry)) {
@@ -955,6 +962,9 @@
       DynamicBaseArg->getOption().getID() == OPT_dynamicbase_no)
     Config->DynamicBase = false;
 
+  // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the
+  // default setting for any other project type.", but link.exe defaults to
+  // /FIXED:NO for exe outputs as well. Match behavior, not docs.
   bool Fixed = Args.hasFlag(OPT_fixed, OPT_fixed_no, false);
   if (Fixed) {
     if (DynamicBaseArg &&
@@ -1021,8 +1031,9 @@
     Config->Implib = Arg->getValue();
 
   // Handle /opt.
-  bool DoGC = !Args.hasArg(OPT_debug);
-  unsigned ICFLevel = 1; // 0: off, 1: limited, 2: on
+  bool DoGC = !Args.hasArg(OPT_debug) || Args.hasArg(OPT_profile);
+  unsigned ICFLevel =
+      Args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on
   for (auto *Arg : Args.filtered(OPT_opt)) {
     std::string Str = StringRef(Arg->getValue()).lower();
     SmallVector<StringRef, 1> Vec;
@@ -1069,6 +1080,10 @@
   if (Args.hasArg(OPT_lldsavetemps))
     Config->SaveTemps = true;
 
+  // Handle /kill-at
+  if (Args.hasArg(OPT_kill_at))
+    Config->KillAt = true;
+
   // Handle /lldltocache
   if (auto *Arg = Args.getLastArg(OPT_lldltocache))
     Config->LTOCache = Arg->getValue();
@@ -1124,7 +1139,7 @@
 
   if (!Config->ManifestInput.empty() &&
       Config->Manifest != Configuration::Embed) {
-    fatal("/MANIFESTINPUT: requires /MANIFEST:EMBED");
+    fatal("/manifestinput: requires /manifest:embed");
   }
 
   // Handle miscellaneous boolean flags.
@@ -1133,7 +1148,8 @@
       Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);
   Config->Incremental =
       Args.hasFlag(OPT_incremental, OPT_incremental_no,
-                   !Config->DoGC && !Config->DoICF && !Args.hasArg(OPT_order));
+                   !Config->DoGC && !Config->DoICF && !Args.hasArg(OPT_order) &&
+                       !Args.hasArg(OPT_profile));
   Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
   Config->TerminalServerAware = Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
   Config->DebugDwarf = Args.hasArg(OPT_debug_dwarf);
@@ -1141,23 +1157,28 @@
 
   Config->MapFile = getMapFile(Args);
 
+  if (Config->Incremental && Args.hasArg(OPT_profile)) {
+    warn("ignoring '/incremental' due to '/profile' specification");
+    Config->Incremental = false;
+  }
+
+  if (Config->Incremental && Args.hasArg(OPT_order)) {
+    warn("ignoring '/incremental' due to '/order' specification");
+    Config->Incremental = false;
+  }
+
   if (Config->Incremental && Config->DoGC) {
-    warn("ignoring '/INCREMENTAL' because REF is enabled; use '/OPT:NOREF' to "
+    warn("ignoring '/incremental' because REF is enabled; use '/opt:noref' to "
          "disable");
     Config->Incremental = false;
   }
 
   if (Config->Incremental && Config->DoICF) {
-    warn("ignoring '/INCREMENTAL' because ICF is enabled; use '/OPT:NOICF' to "
+    warn("ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to "
          "disable");
     Config->Incremental = false;
   }
 
-  if (Config->Incremental && Args.hasArg(OPT_order)) {
-    warn("ignoring '/INCREMENTAL' due to '/ORDER' specification");
-    Config->Incremental = false;
-  }
-
   if (errorCount())
     return;
 
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
index 1191530..0b705f4 100644
--- a/COFF/DriverUtils.cpp
+++ b/COFF/DriverUtils.cpp
@@ -139,7 +139,7 @@
     else if (Arg.equals_lower("cf") || Arg.equals_lower("longjmp"))
       Config->GuardCF = GuardCFLevel::Full;
     else
-      fatal("invalid argument to /GUARD: " + Arg);
+      fatal("invalid argument to /guard: " + Arg);
   }
 }
 
@@ -582,6 +582,26 @@
   return Sym.startswith("_") ? Sym.substr(1) : Sym;
 }
 
+// Convert stdcall/fastcall style symbols into unsuffixed symbols,
+// with or without a leading underscore. (MinGW specific.)
+static StringRef killAt(StringRef Sym, bool Prefix) {
+  if (Sym.empty())
+    return Sym;
+  // Strip any trailing stdcall suffix
+  Sym = Sym.substr(0, Sym.find('@', 1));
+  if (!Sym.startswith("@")) {
+    if (Prefix && !Sym.startswith("_"))
+      return Saver.save("_" + Sym);
+    return Sym;
+  }
+  // For fastcall, remove the leading @ and replace it with an
+  // underscore, if prefixes are used.
+  Sym = Sym.substr(1);
+  if (Prefix)
+    Sym = Saver.save("_" + Sym);
+  return Sym;
+}
+
 // Performs error checking on all /export arguments.
 // It also sets ordinals.
 void fixupExports() {
@@ -614,6 +634,15 @@
     }
   }
 
+  if (Config->KillAt && Config->Machine == I386) {
+    for (Export &E : Config->Exports) {
+      E.Name = killAt(E.Name, true);
+      E.ExportName = killAt(E.ExportName, false);
+      E.ExtName = killAt(E.ExtName, true);
+      E.SymbolName = killAt(E.SymbolName, true);
+    }
+  }
+
   // Uniquefy by name.
   DenseMap<StringRef, Export *> Map(Config->Exports.size());
   std::vector<Export> V;
diff --git a/COFF/ICF.cpp b/COFF/ICF.cpp
index c063ab2..77c05b7 100644
--- a/COFF/ICF.cpp
+++ b/COFF/ICF.cpp
@@ -168,6 +168,7 @@
   return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq);
 }
 
+// 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])
@@ -177,11 +178,8 @@
 
 void ICF::forEachClassRange(size_t Begin, size_t End,
                             std::function<void(size_t, size_t)> Fn) {
-  if (Begin > 0)
-    Begin = findBoundary(Begin - 1, End);
-
   while (Begin < End) {
-    size_t Mid = findBoundary(Begin, Chunks.size());
+    size_t Mid = findBoundary(Begin, End);
     Fn(Begin, Mid);
     Begin = Mid;
   }
@@ -197,12 +195,22 @@
     return;
   }
 
-  // Split sections into 256 shards and call Fn in parallel.
-  size_t NumShards = 256;
+  // 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;
-  for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
-    size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
-    forEachClassRange(I * Step, End, Fn);
+  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;
 }
@@ -224,6 +232,12 @@
     }
   }
 
+  // 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.
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp
index b60e8c8..78bfe34 100644
--- a/COFF/InputFiles.cpp
+++ b/COFF/InputFiles.cpp
@@ -138,12 +138,13 @@
     if (Sec->Characteristics & IMAGE_SCN_LNK_COMDAT)
       SparseChunks[I] = PendingComdat;
     else
-      SparseChunks[I] = readSection(I, nullptr);
+      SparseChunks[I] = readSection(I, nullptr, "");
   }
 }
 
 SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
-                                   const coff_aux_section_definition *Def) {
+                                   const coff_aux_section_definition *Def,
+                                   StringRef LeaderName) {
   const coff_section *Sec;
   StringRef Name;
   if (auto EC = COFFObj->getSection(SectionNumber, Sec))
@@ -189,6 +190,12 @@
     GuardLJmpChunks.push_back(C);
   else if (Name == ".sxdata")
     SXDataChunks.push_back(C);
+  else if (Config->DoICF && Sec->NumberOfRelocations == 0 && Name == ".rdata" &&
+           LeaderName.startswith("??_C@"))
+    // COFF sections that look like string literal sections (i.e. no
+    // relocations, in .rdata, leader symbol name matches the MSVC name mangling
+    // for string literals) are subject to string tail merging.
+    MergeChunk::addSection(C);
   else
     Chunks.push_back(C);
 
@@ -209,7 +216,7 @@
   // the section; otherwise mark it as discarded.
   int32_t SectionNumber = Sym.getSectionNumber();
   if (Parent) {
-    SparseChunks[SectionNumber] = readSection(SectionNumber, Def);
+    SparseChunks[SectionNumber] = readSection(SectionNumber, Def, "");
     if (SparseChunks[SectionNumber])
       Parent->addAssociative(SparseChunks[SectionNumber]);
   } else {
@@ -343,7 +350,7 @@
       Prevailing = true;
     }
     if (Prevailing) {
-      SectionChunk *C = readSection(SectionNumber, Def);
+      SectionChunk *C = readSection(SectionNumber, Def, Name);
       SparseChunks[SectionNumber] = C;
       C->Sym = cast<DefinedRegular>(Leader);
       cast<DefinedRegular>(Leader)->Data = &C->Repl;
diff --git a/COFF/InputFiles.h b/COFF/InputFiles.h
index 000fdc6..3ee5780 100644
--- a/COFF/InputFiles.h
+++ b/COFF/InputFiles.h
@@ -150,7 +150,8 @@
 
   SectionChunk *
   readSection(uint32_t SectionNumber,
-              const llvm::object::coff_aux_section_definition *Def);
+              const llvm::object::coff_aux_section_definition *Def,
+              StringRef LeaderName);
 
   void readAssociativeDefinition(
       COFFSymbolRef COFFSym,
diff --git a/COFF/LTO.cpp b/COFF/LTO.cpp
index 8a1c82c..56ca8c0 100644
--- a/COFF/LTO.cpp
+++ b/COFF/LTO.cpp
@@ -64,6 +64,12 @@
 static std::unique_ptr<lto::LTO> createLTO() {
   lto::Config Conf;
   Conf.Options = InitTargetOptionsFromCodeGenFlags();
+
+  // Always emit a section per function/datum with LTO. LLVM LTO should get most
+  // of the benefit of linker GC, but there are still opportunities for ICF.
+  Conf.Options.FunctionSections = true;
+  Conf.Options.DataSections = true;
+
   // Use static reloc model on 32-bit x86 because it usually results in more
   // compact code, and because there are also known code generation bugs when
   // using the PIC model (see PR34306).
diff --git a/COFF/MapFile.cpp b/COFF/MapFile.cpp
index d475641..6ca1b66 100644
--- a/COFF/MapFile.cpp
+++ b/COFF/MapFile.cpp
@@ -36,14 +36,15 @@
 typedef DenseMap<const SectionChunk *, SmallVector<DefinedRegular *, 4>>
     SymbolMapTy;
 
+static const std::string Indent8 = "        ";          // 8 spaces
+static const std::string Indent16 = "                "; // 16 spaces
+
 // Print out the first three columns of a line.
 static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size,
                         uint64_t Align) {
   OS << format("%08llx %08llx %5lld ", Addr, Size, Align);
 }
 
-static std::string indent(int Depth) { return std::string(Depth * 8, ' '); }
-
 // Returns a list of all symbols that we want to print out.
 static std::vector<DefinedRegular *> getSymbols() {
   std::vector<DefinedRegular *> V;
@@ -78,7 +79,7 @@
   for_each_n(parallel::par, (size_t)0, Syms.size(), [&](size_t I) {
     raw_string_ostream OS(Str[I]);
     writeHeader(OS, Syms[I]->getRVA(), 0, 0);
-    OS << indent(2) << toString(*Syms[I]);
+    OS << Indent16 << toString(*Syms[I]);
   });
 
   DenseMap<DefinedRegular *, std::string> Ret;
@@ -107,7 +108,7 @@
   // Print out file contents.
   for (OutputSection *Sec : OutputSections) {
     writeHeader(OS, Sec->getRVA(), Sec->getVirtualSize(), /*Align=*/PageSize);
-    OS << Sec->getName() << '\n';
+    OS << Sec->Name << '\n';
 
     for (Chunk *C : Sec->getChunks()) {
       auto *SC = dyn_cast<SectionChunk>(C);
@@ -115,7 +116,7 @@
         continue;
 
       writeHeader(OS, SC->getRVA(), SC->getSize(), SC->Alignment);
-      OS << indent(1) << SC->File->getName() << ":(" << SC->getSectionName()
+      OS << Indent8 << SC->File->getName() << ":(" << SC->getSectionName()
          << ")\n";
       for (DefinedRegular *Sym : SectionSyms[SC])
         OS << SymStr[Sym] << '\n';
diff --git a/COFF/Options.td b/COFF/Options.td
index d9531b5..243671d 100644
--- a/COFF/Options.td
+++ b/COFF/Options.td
@@ -45,6 +45,7 @@
 def opt     : P<"opt", "Control optimizations">;
 def order   : P<"order", "Put functions in order">;
 def out     : P<"out", "Path to file to write output">;
+def natvis : P<"natvis", "Path to natvis file to embed in the PDB">;
 def pdb : P<"pdb", "PDB file path">;
 def section : P<"section", "Specify section attributes">;
 def stack   : P<"stack", "Size of the stack">;
@@ -126,6 +127,7 @@
 def debug_ghash : F<"debug:ghash">;
 def debug_dwarf : F<"debug:dwarf">;
 def export_all_symbols : F<"export-all-symbols">;
+def kill_at : F<"kill-at">;
 def lldmingw : F<"lldmingw">;
 def msvclto : F<"msvclto">;
 def output_def : Joined<["/", "-"], "output-def:">;
@@ -161,7 +163,6 @@
 def errorreport : QF<"errorreport">;
 def idlout : QF<"idlout">;
 def maxilksize : QF<"maxilksize">;
-def natvis : QF<"natvis">;
 def pdbaltpath : QF<"pdbaltpath">;
 def tlbid : QF<"tlbid">;
 def tlbout : QF<"tlbout">;
diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp
index de6aa64..91131c6 100644
--- a/COFF/PDB.cpp
+++ b/COFF/PDB.cpp
@@ -16,7 +16,6 @@
 #include "Writer.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Timer.h"
-#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
 #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@@ -46,6 +45,7 @@
 #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
 #include "llvm/DebugInfo/PDB/PDB.h"
 #include "llvm/Object/COFF.h"
+#include "llvm/Object/CVDebugRecord.h"
 #include "llvm/Support/BinaryByteStream.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -85,11 +85,19 @@
 public:
   PDBLinker(SymbolTable *Symtab)
       : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc),
-        IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) {}
+        IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) {
+    // This isn't strictly necessary, but link.exe usually puts an empty string
+    // as the first "valid" string in the string table, so we do the same in
+    // order to maintain as much byte-for-byte compatibility as possible.
+    PDBStrTab.insert("");
+  }
 
   /// Emit the basic PDB structure: initial streams, headers, etc.
   void initialize(const llvm::codeview::DebugInfo &BuildId);
 
+  /// Add natvis files specified on the command line.
+  void addNatvisFiles();
+
   /// Link CodeView from each object file in the symbol table into the PDB.
   void addObjectsToPDB();
 
@@ -961,6 +969,18 @@
   }
 }
 
+void PDBLinker::addNatvisFiles() {
+  for (StringRef File : Config->NatvisFiles) {
+    ErrorOr<std::unique_ptr<MemoryBuffer>> DataOrErr =
+        MemoryBuffer::getFile(File);
+    if (!DataOrErr) {
+      warn("Cannot open input file: " + File);
+      continue;
+    }
+    Builder.addInjectedSource(File, std::move(*DataOrErr));
+  }
+}
+
 static void addCommonLinkerModuleSymbols(StringRef Path,
                                          pdb::DbiModuleDescriptorBuilder &Mod,
                                          BumpPtrAllocator &Allocator) {
@@ -1024,7 +1044,7 @@
   Sym.Alignment = 12; // 2^12 = 4KB
   Sym.Characteristics = OS.getCharacteristics();
   Sym.Length = OS.getVirtualSize();
-  Sym.Name = OS.getName();
+  Sym.Name = OS.Name;
   Sym.Rva = OS.getRVA();
   Sym.SectionNumber = OS.SectionIndex;
   Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
@@ -1038,9 +1058,11 @@
                      const llvm::codeview::DebugInfo &BuildId) {
   ScopedTimer T1(TotalPdbLinkTimer);
   PDBLinker PDB(Symtab);
+
   PDB.initialize(BuildId);
   PDB.addObjectsToPDB();
   PDB.addSections(OutputSections, SectionTable);
+  PDB.addNatvisFiles();
 
   ScopedTimer T2(DiskCommitTimer);
   PDB.commit();
@@ -1066,7 +1088,6 @@
   pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
   DbiBuilder.setAge(BuildId.PDB70.Age);
   DbiBuilder.setVersionHeader(pdb::PdbDbiV70);
-  ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
 }
 
 void PDBLinker::addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule,
diff --git a/COFF/SymbolTable.cpp b/COFF/SymbolTable.cpp
index 73d5407..32420df 100644
--- a/COFF/SymbolTable.cpp
+++ b/COFF/SymbolTable.cpp
@@ -123,7 +123,7 @@
     if (Config->WarnLocallyDefinedImported)
       if (Symbol *Imp = LocalImports.lookup(B))
         warn("<root>: locally defined symbol imported: " + Imp->getName() +
-             " (defined in " + toString(Imp->getFile()) + ")");
+             " (defined in " + toString(Imp->getFile()) + ") [LNK4217]");
   }
 
   for (ObjFile *File : ObjFile::Instances) {
@@ -136,7 +136,7 @@
         if (Symbol *Imp = LocalImports.lookup(Sym))
           warn(toString(File) + ": locally defined symbol imported: " +
                Imp->getName() + " (defined in " + toString(Imp->getFile()) +
-               ")");
+               ") [LNK4217]");
     }
   }
 }
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp
index bb621eb..6f173de 100644
--- a/COFF/Writer.cpp
+++ b/COFF/Writer.cpp
@@ -28,6 +28,7 @@
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Support/xxhash.h"
 #include <algorithm>
 #include <cstdio>
 #include <map>
@@ -42,8 +43,40 @@
 using namespace lld;
 using namespace lld::coff;
 
+/* To re-generate DOSProgram:
+$ cat > /tmp/DOSProgram.asm
+org 0
+        ; Copy cs to ds.
+        push cs
+        pop ds
+        ; Point ds:dx at the $-terminated string.
+        mov dx, str
+        ; Int 21/AH=09h: Write string to standard output.
+        mov ah, 0x9
+        int 0x21
+        ; Int 21/AH=4Ch: Exit with return code (in AL).
+        mov ax, 0x4C01
+        int 0x21
+str:
+        db 'This program cannot be run in DOS mode.$'
+align 8, db 0
+$ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin
+$ xxd -i /tmp/DOSProgram.bin
+*/
+static unsigned char DOSProgram[] = {
+  0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c,
+  0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
+  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
+  0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
+  0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00
+};
+static_assert(sizeof(DOSProgram) % 8 == 0,
+              "DOSProgram size must be multiple of 8");
+
 static const int SectorSize = 512;
-static const int DOSStubSize = 64;
+static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram);
+static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8");
+
 static const int NumberfOfDataDirectory = 16;
 
 namespace {
@@ -71,11 +104,18 @@
       uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA());
       D->PointerToRawData = Offs;
 
+      TimeDateStamps.push_back(&D->TimeDateStamp);
       ++D;
     }
   }
 
+  void setTimeDateStamp(uint32_t TimeDateStamp) {
+    for (support::ulittle32_t *TDS : TimeDateStamps)
+      *TDS = TimeDateStamp;
+  }
+
 private:
+  mutable std::vector<support::ulittle32_t *> TimeDateStamps;
   const std::vector<Chunk *> &Records;
 };
 
@@ -157,7 +197,7 @@
   RVATableChunk *GuardFidsTable = nullptr;
   RVATableChunk *SEHTable = nullptr;
 
-  Chunk *DebugDirectory = nullptr;
+  DebugDirectoryChunk *DebugDirectory = nullptr;
   std::vector<Chunk *> DebugRecords;
   CVDebugRecordChunk *BuildId = nullptr;
   Optional<codeview::DebugInfo> PreviousBuildId;
@@ -178,37 +218,9 @@
 
 void writeResult() { Writer().run(); }
 
-void OutputSection::setRVA(uint64_t RVA) {
-  Header.VirtualAddress = RVA;
-  for (Chunk *C : Chunks)
-    C->setRVA(C->getRVA() + RVA);
-}
-
-void OutputSection::setFileOffset(uint64_t Off) {
-  // If a section has no actual data (i.e. BSS section), we want to
-  // set 0 to its PointerToRawData. Otherwise the output is rejected
-  // by the loader.
-  if (Header.SizeOfRawData == 0)
-    return;
-
-  // It is possible that this assignment could cause an overflow of the u32,
-  // but that should be caught by the FileSize check in OutputSection::run().
-  Header.PointerToRawData = Off;
-}
-
 void OutputSection::addChunk(Chunk *C) {
   Chunks.push_back(C);
   C->setOutputSection(this);
-  uint64_t Off = Header.VirtualSize;
-  Off = alignTo(Off, C->Alignment);
-  C->setRVA(Off);
-  C->OutputSectionOff = Off;
-  Off += C->getSize();
-  if (Off > UINT32_MAX)
-    error("section larger than 4 GiB: " + Name);
-  Header.VirtualSize = Off;
-  if (C->hasData())
-    Header.SizeOfRawData = alignTo(Off, SectorSize);
 }
 
 void OutputSection::addPermissions(uint32_t C) {
@@ -414,6 +426,9 @@
 void Writer::createMiscChunks() {
   OutputSection *RData = createSection(".rdata");
 
+  for (auto &P : MergeChunk::Instances)
+    RData->addChunk(P.second);
+
   // Create thunks for locally-dllimported symbols.
   if (!Symtab->LocalImportChunks.empty()) {
     for (Chunk *C : Symtab->LocalImportChunks)
@@ -588,19 +603,20 @@
 }
 
 void Writer::createSymbolAndStringTable() {
-  // Name field in the section table is 8 byte long. Longer names need
-  // to be written to the string table. First, construct string table.
+  // PE/COFF images are limited to 8 byte section names. Longer names can be
+  // supported by writing a non-standard string table, but this string table is
+  // not mapped at runtime and the long names will therefore be inaccessible.
+  // link.exe always truncates section names to 8 bytes, whereas binutils always
+  // preserves long section names via the string table. LLD adopts a hybrid
+  // solution where discardable sections have long names preserved and
+  // non-discardable sections have their names truncated, to ensure that any
+  // section which is mapped at runtime also has its name mapped at runtime.
   for (OutputSection *Sec : OutputSections) {
-    StringRef Name = Sec->getName();
-    if (Name.size() <= COFF::NameSize)
+    if (Sec->Name.size() <= COFF::NameSize)
       continue;
-    // If a section isn't discardable (i.e. will be mapped at runtime),
-    // prefer a truncated section name over a long section name in
-    // the string table that is unavailable at runtime. Note that link.exe
-    // always truncates, even for discardable sections.
     if ((Sec->getPermissions() & IMAGE_SCN_MEM_DISCARDABLE) == 0)
       continue;
-    Sec->setStringTableOff(addEntryToStringTable(Name));
+    Sec->setStringTableOff(addEntryToStringTable(Sec->Name));
   }
 
   if (Config->DebugDwarf) {
@@ -646,26 +662,53 @@
         return (S->getPermissions() & IMAGE_SCN_MEM_DISCARDABLE) == 0;
       });
   for (OutputSection *Sec : OutputSections) {
-    if (Sec->getName() == ".reloc")
+    if (Sec->Name == ".reloc")
       addBaserels(Sec);
-    Sec->setRVA(RVA);
-    Sec->setFileOffset(FileSize);
-    RVA += alignTo(Sec->getVirtualSize(), PageSize);
-    FileSize += alignTo(Sec->getRawSize(), SectorSize);
+    uint64_t RawSize = 0, VirtualSize = 0;
+    Sec->Header.VirtualAddress = RVA;
+    for (Chunk *C : Sec->getChunks()) {
+      VirtualSize = alignTo(VirtualSize, C->Alignment);
+      C->setRVA(RVA + VirtualSize);
+      C->OutputSectionOff = VirtualSize;
+      C->finalizeContents();
+      VirtualSize += C->getSize();
+      if (C->hasData())
+        RawSize = alignTo(VirtualSize, SectorSize);
+    }
+    if (VirtualSize > UINT32_MAX)
+      error("section larger than 4 GiB: " + Sec->Name);
+    Sec->Header.VirtualSize = VirtualSize;
+    Sec->Header.SizeOfRawData = RawSize;
+    if (RawSize != 0)
+      Sec->Header.PointerToRawData = FileSize;
+    RVA += alignTo(VirtualSize, PageSize);
+    FileSize += alignTo(RawSize, SectorSize);
   }
   SizeOfImage = alignTo(RVA, PageSize);
 }
 
 template <typename PEHeaderTy> void Writer::writeHeader() {
-  // Write DOS stub
+  // Write DOS header. For backwards compatibility, the first part of a PE/COFF
+  // executable consists of an MS-DOS MZ executable. If the executable is run
+  // under DOS, that program gets run (usually to just print an error message).
+  // When run under Windows, the loader looks at AddressOfNewExeHeader and uses
+  // the PE header instead.
   uint8_t *Buf = Buffer->getBufferStart();
   auto *DOS = reinterpret_cast<dos_header *>(Buf);
-  Buf += DOSStubSize;
+  Buf += sizeof(dos_header);
   DOS->Magic[0] = 'M';
   DOS->Magic[1] = 'Z';
+  DOS->UsedBytesInTheLastPage = DOSStubSize % 512;
+  DOS->FileSizeInPages = divideCeil(DOSStubSize, 512);
+  DOS->HeaderSizeInParagraphs = sizeof(dos_header) / 16;
+
   DOS->AddressOfRelocationTable = sizeof(dos_header);
   DOS->AddressOfNewExeHeader = DOSStubSize;
 
+  // Write DOS program.
+  memcpy(Buf, DOSProgram, sizeof(DOSProgram));
+  Buf += sizeof(DOSProgram);
+
   // Write PE magic
   memcpy(Buf, PEMagic, sizeof(PEMagic));
   Buf += sizeof(PEMagic);
@@ -1026,22 +1069,50 @@
 }
 
 void Writer::writeBuildId() {
-  // If we're not writing a build id (e.g. because /debug is not specified),
-  // then just return;
-  if (!Config->Debug)
-    return;
-
-  assert(BuildId && "BuildId is not set!");
-
-  if (PreviousBuildId.hasValue()) {
-    *BuildId->BuildId = *PreviousBuildId;
-    BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
-    return;
+  // There are two important parts to the build ID.
+  // 1) If building with debug info, the COFF debug directory contains a
+  //    timestamp as well as a Guid and Age of the PDB.
+  // 2) In all cases, the PE COFF file header also contains a timestamp.
+  // For reproducibility, instead of a timestamp we want to use a hash of the
+  // binary, however when building with debug info the hash needs to take into
+  // account the debug info, since it's possible to add blank lines to a file
+  // which causes the debug info to change but not the generated code.
+  //
+  // To handle this, we first set the Guid and Age in the debug directory (but
+  // only if we're doing a debug build).  Then, we hash the binary (thus causing
+  // the hash to change if only the debug info changes, since the Age will be
+  // different).  Finally, we write that hash into the debug directory (if
+  // present) as well as the COFF file header (always).
+  if (Config->Debug) {
+    assert(BuildId && "BuildId is not set!");
+    if (PreviousBuildId.hasValue()) {
+      *BuildId->BuildId = *PreviousBuildId;
+      BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1;
+    } else {
+      BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
+      BuildId->BuildId->PDB70.Age = 1;
+      llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
+    }
   }
 
-  BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70;
-  BuildId->BuildId->PDB70.Age = 1;
-  llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16);
+  // At this point the only fields in the COFF file which remain unset are the
+  // "timestamp" in the COFF file header, and the ones in the coff debug
+  // directory.  Now we can hash the file and write that hash to the various
+  // timestamp fields in the file.
+  StringRef OutputFileData(
+      reinterpret_cast<const char *>(Buffer->getBufferStart()),
+      Buffer->getBufferSize());
+
+  uint32_t Hash = static_cast<uint32_t>(xxHash64(OutputFileData));
+
+  if (DebugDirectory)
+    DebugDirectory->setTimeDateStamp(Hash);
+
+  uint8_t *Buf = Buffer->getBufferStart();
+  Buf += DOSStubSize + sizeof(PEMagic);
+  object::coff_file_header *CoffHeader =
+      reinterpret_cast<coff_file_header *>(Buf);
+  CoffHeader->TimeDateStamp = Hash;
 }
 
 // Sort .pdata section contents according to PE/COFF spec 5.5.
@@ -1069,7 +1140,7 @@
 
 OutputSection *Writer::findSection(StringRef Name) {
   for (OutputSection *Sec : OutputSections)
-    if (Sec->getName() == Name)
+    if (Sec->Name == Name)
       return Sec;
   return nullptr;
 }
diff --git a/COFF/Writer.h b/COFF/Writer.h
index c8e8dc8..1dc1e61 100644
--- a/COFF/Writer.h
+++ b/COFF/Writer.h
@@ -31,10 +31,7 @@
 class OutputSection {
 public:
   OutputSection(llvm::StringRef N) : Name(N), Header({}) {}
-  void setRVA(uint64_t);
-  void setFileOffset(uint64_t);
   void addChunk(Chunk *C);
-  llvm::StringRef getName() { return Name; }
   ArrayRef<Chunk *> getChunks() { return Chunks; }
   void addPermissions(uint32_t C);
   void setPermissions(uint32_t C);
@@ -61,9 +58,10 @@
   // N.B. The section index is one based.
   uint32_t SectionIndex = 0;
 
-private:
   llvm::StringRef Name;
   llvm::object::coff_section Header;
+
+private:
   uint32_t StringTableOff = 0;
   std::vector<Chunk *> Chunks;
 };
diff --git a/ELF/AArch64ErrataFix.cpp b/ELF/AArch64ErrataFix.cpp
index 2924b19..7551919 100644
--- a/ELF/AArch64ErrataFix.cpp
+++ b/ELF/AArch64ErrataFix.cpp
@@ -341,7 +341,7 @@
 // patch or 0 if no patch required.
 static uint64_t scanCortexA53Errata843419(InputSection *IS, uint64_t &Off,
                                           uint64_t Limit) {
-  uint64_t ISAddr = IS->getParent()->Addr + IS->OutSecOff;
+  uint64_t ISAddr = IS->getVA(0);
 
   // Advance Off so that (ISAddr + Off) modulo 0x1000 is at least 0xff8.
   uint64_t InitialPageOff = (ISAddr + Off) & 0xfff;
@@ -405,7 +405,7 @@
 }
 
 uint64_t lld::elf::Patch843419Section::getLDSTAddr() const {
-  return Patchee->getParent()->Addr + Patchee->OutSecOff + PatcheeOffset;
+  return Patchee->getVA(PatcheeOffset);
 }
 
 void lld::elf::Patch843419Section::writeTo(uint8_t *Buf) {
@@ -601,7 +601,7 @@
           (DataSym == MapSyms.end()) ? IS->Data.size() : (*DataSym)->Value;
 
       while (Off < Limit) {
-        uint64_t StartAddr = IS->getParent()->Addr + IS->OutSecOff + Off;
+        uint64_t StartAddr = IS->getVA(Off);
         if (uint64_t PatcheeOffset = scanCortexA53Errata843419(IS, Off, Limit))
           implementPatch(StartAddr, PatcheeOffset, IS, Patches);
       }
diff --git a/ELF/Arch/AArch64.cpp b/ELF/Arch/AArch64.cpp
index 99e9879..2307ed1 100644
--- a/ELF/Arch/AArch64.cpp
+++ b/ELF/Arch/AArch64.cpp
@@ -240,12 +240,12 @@
   switch (Type) {
   case R_AARCH64_ABS16:
   case R_AARCH64_PREL16:
-    checkIntUInt<16>(Loc, Val, Type);
+    checkIntUInt(Loc, Val, 16, Type);
     write16le(Loc, Val);
     break;
   case R_AARCH64_ABS32:
   case R_AARCH64_PREL32:
-    checkIntUInt<32>(Loc, Val, Type);
+    checkIntUInt(Loc, Val, 32, Type);
     write32le(Loc, Val);
     break;
   case R_AARCH64_ABS64:
@@ -260,11 +260,11 @@
   case R_AARCH64_ADR_PREL_PG_HI21:
   case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
   case R_AARCH64_TLSDESC_ADR_PAGE21:
-    checkInt<33>(Loc, Val, Type);
+    checkInt(Loc, Val, 33, Type);
     write32AArch64Addr(Loc, Val >> 12);
     break;
   case R_AARCH64_ADR_PREL_LO21:
-    checkInt<21>(Loc, Val, Type);
+    checkInt(Loc, Val, 21, Type);
     write32AArch64Addr(Loc, Val);
     break;
   case R_AARCH64_JUMP26:
@@ -278,38 +278,38 @@
     write32le(Loc, 0x14000000);
     LLVM_FALLTHROUGH;
   case R_AARCH64_CALL26:
-    checkInt<28>(Loc, Val, Type);
+    checkInt(Loc, Val, 28, Type);
     or32le(Loc, (Val & 0x0FFFFFFC) >> 2);
     break;
   case R_AARCH64_CONDBR19:
   case R_AARCH64_LD_PREL_LO19:
-    checkAlignment<4>(Loc, Val, Type);
-    checkInt<21>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 4, Type);
+    checkInt(Loc, Val, 21, Type);
     or32le(Loc, (Val & 0x1FFFFC) << 3);
     break;
   case R_AARCH64_LD64_GOT_LO12_NC:
   case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
   case R_AARCH64_TLSDESC_LD64_LO12:
-    checkAlignment<8>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 8, Type);
     or32le(Loc, (Val & 0xFF8) << 7);
     break;
   case R_AARCH64_LDST8_ABS_LO12_NC:
     or32AArch64Imm(Loc, getBits(Val, 0, 11));
     break;
   case R_AARCH64_LDST16_ABS_LO12_NC:
-    checkAlignment<2>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 2, Type);
     or32AArch64Imm(Loc, getBits(Val, 1, 11));
     break;
   case R_AARCH64_LDST32_ABS_LO12_NC:
-    checkAlignment<4>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 4, Type);
     or32AArch64Imm(Loc, getBits(Val, 2, 11));
     break;
   case R_AARCH64_LDST64_ABS_LO12_NC:
-    checkAlignment<8>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 8, Type);
     or32AArch64Imm(Loc, getBits(Val, 3, 11));
     break;
   case R_AARCH64_LDST128_ABS_LO12_NC:
-    checkAlignment<16>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 16, Type);
     or32AArch64Imm(Loc, getBits(Val, 4, 11));
     break;
   case R_AARCH64_MOVW_UABS_G0_NC:
@@ -325,11 +325,11 @@
     or32le(Loc, (Val & 0xFFFF000000000000) >> 43);
     break;
   case R_AARCH64_TSTBR14:
-    checkInt<16>(Loc, Val, Type);
+    checkInt(Loc, Val, 16, Type);
     or32le(Loc, (Val & 0xFFFC) << 3);
     break;
   case R_AARCH64_TLSLE_ADD_TPREL_HI12:
-    checkInt<24>(Loc, Val, Type);
+    checkInt(Loc, Val, 24, Type);
     or32AArch64Imm(Loc, Val >> 12);
     break;
   case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
@@ -353,7 +353,7 @@
   //   movk    x0, #0x10
   //   nop
   //   nop
-  checkUInt<32>(Loc, Val, Type);
+  checkUInt(Loc, Val, 32, Type);
 
   switch (Type) {
   case R_AARCH64_TLSDESC_ADD_LO12:
@@ -403,7 +403,7 @@
 }
 
 void AArch64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
-  checkUInt<32>(Loc, Val, Type);
+  checkUInt(Loc, Val, 32, Type);
 
   if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
     // Generate MOVZ.
diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp
index b9f551e..9927430 100644
--- a/ELF/Arch/ARM.cpp
+++ b/ELF/Arch/ARM.cpp
@@ -55,6 +55,7 @@
   TlsGotRel = R_ARM_TLS_TPOFF32;
   TlsModuleIndexRel = R_ARM_TLS_DTPMOD32;
   TlsOffsetRel = R_ARM_TLS_DTPOFF32;
+  GotBaseSymInGotPlt = false;
   GotEntrySize = 4;
   GotPltEntrySize = 4;
   PltEntrySize = 16;
@@ -392,7 +393,7 @@
     write32le(Loc, 1);
     break;
   case R_ARM_PREL31:
-    checkInt<31>(Loc, Val, Type);
+    checkInt(Loc, Val, 31, Type);
     write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000));
     break;
   case R_ARM_CALL:
@@ -401,7 +402,7 @@
     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<26>(Loc, Val, Type);
+      checkInt(Loc, Val, 26, Type);
       write32le(Loc, 0xfa000000 |                    // opcode
                          ((Val & 2) << 23) |         // H
                          ((Val >> 2) & 0x00ffffff)); // imm24
@@ -416,16 +417,16 @@
   case R_ARM_JUMP24:
   case R_ARM_PC24:
   case R_ARM_PLT32:
-    checkInt<26>(Loc, Val, Type);
+    checkInt(Loc, Val, 26, Type);
     write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff));
     break;
   case R_ARM_THM_JUMP11:
-    checkInt<12>(Loc, Val, Type);
+    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<21>(Loc, Val, Type);
+    checkInt(Loc, Val, 21, Type);
     write16le(Loc,
               (read16le(Loc) & 0xfbc0) |   // opcode cond
                   ((Val >> 10) & 0x0400) | // S
@@ -451,7 +452,7 @@
   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<25>(Loc, Val, Type);
+    checkInt(Loc, Val, 25, Type);
     write16le(Loc,
               0xf000 |                     // opcode
                   ((Val >> 14) & 0x0400) | // S
@@ -469,14 +470,14 @@
     break;
   case R_ARM_MOVT_ABS:
   case R_ARM_MOVT_PREL:
-    checkInt<32>(Loc, Val, Type);
+    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<32>(Loc, Val, Type);
+    checkInt(Loc, Val, 32, Type);
     write16le(Loc,
               0xf2c0 |                     // opcode
                   ((Val >> 17) & 0x0400) | // i
diff --git a/ELF/Arch/Mips.cpp b/ELF/Arch/Mips.cpp
index fcf5aff..a8e54a8 100644
--- a/ELF/Arch/Mips.cpp
+++ b/ELF/Arch/Mips.cpp
@@ -50,6 +50,7 @@
   DefaultMaxPageSize = 65536;
   GotEntrySize = sizeof(typename ELFT::uint);
   GotPltEntrySize = sizeof(typename ELFT::uint);
+  GotBaseSymInGotPlt = false;
   PltEntrySize = 16;
   PltHeaderSize = 32;
   CopyRel = R_MIPS_COPY;
@@ -510,7 +511,7 @@
     if (Config->Relocatable) {
       writeValue<E>(Loc, Val + 0x8000, 16, 16);
     } else {
-      checkInt<16>(Loc, Val, Type);
+      checkInt(Loc, Val, 16, Type);
       writeValue<E>(Loc, Val, 16, 0);
     }
     break;
@@ -518,7 +519,7 @@
     if (Config->Relocatable) {
       writeShuffleValue<E>(Loc, Val + 0x8000, 16, 16);
     } else {
-      checkInt<16>(Loc, Val, Type);
+      checkInt(Loc, Val, 16, Type);
       writeShuffleValue<E>(Loc, Val, 16, 0);
     }
     break;
@@ -529,7 +530,7 @@
   case R_MIPS_TLS_GD:
   case R_MIPS_TLS_GOTTPREL:
   case R_MIPS_TLS_LDM:
-    checkInt<16>(Loc, Val, Type);
+    checkInt(Loc, Val, 16, Type);
     LLVM_FALLTHROUGH;
   case R_MIPS_CALL_LO16:
   case R_MIPS_GOT_LO16:
@@ -545,7 +546,7 @@
   case R_MICROMIPS_GPREL16:
   case R_MICROMIPS_TLS_GD:
   case R_MICROMIPS_TLS_LDM:
-    checkInt<16>(Loc, Val, Type);
+    checkInt(Loc, Val, 16, Type);
     writeShuffleValue<E>(Loc, Val, 16, 0);
     break;
   case R_MICROMIPS_CALL16:
@@ -558,7 +559,7 @@
     writeShuffleValue<E>(Loc, Val, 16, 0);
     break;
   case R_MICROMIPS_GPREL7_S2:
-    checkInt<7>(Loc, Val, Type);
+    checkInt(Loc, Val, 7, Type);
     writeShuffleValue<E>(Loc, Val, 7, 2);
     break;
   case R_MIPS_CALL_HI16:
@@ -593,23 +594,23 @@
     // Ignore this optimization relocation for now
     break;
   case R_MIPS_PC16:
-    checkAlignment<4>(Loc, Val, Type);
-    checkInt<18>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 4, Type);
+    checkInt(Loc, Val, 18, Type);
     writeValue<E>(Loc, Val, 16, 2);
     break;
   case R_MIPS_PC19_S2:
-    checkAlignment<4>(Loc, Val, Type);
-    checkInt<21>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 4, Type);
+    checkInt(Loc, Val, 21, Type);
     writeValue<E>(Loc, Val, 19, 2);
     break;
   case R_MIPS_PC21_S2:
-    checkAlignment<4>(Loc, Val, Type);
-    checkInt<23>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 4, Type);
+    checkInt(Loc, Val, 23, Type);
     writeValue<E>(Loc, Val, 21, 2);
     break;
   case R_MIPS_PC26_S2:
-    checkAlignment<4>(Loc, Val, Type);
-    checkInt<28>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 4, Type);
+    checkInt(Loc, Val, 28, Type);
     writeValue<E>(Loc, Val, 26, 2);
     break;
   case R_MIPS_PC32:
@@ -617,35 +618,35 @@
     break;
   case R_MICROMIPS_26_S1:
   case R_MICROMIPS_PC26_S1:
-    checkInt<27>(Loc, Val, Type);
+    checkInt(Loc, Val, 27, Type);
     writeShuffleValue<E>(Loc, Val, 26, 1);
     break;
   case R_MICROMIPS_PC7_S1:
-    checkInt<8>(Loc, Val, Type);
+    checkInt(Loc, Val, 8, Type);
     writeMicroRelocation16<E>(Loc, Val, 7, 1);
     break;
   case R_MICROMIPS_PC10_S1:
-    checkInt<11>(Loc, Val, Type);
+    checkInt(Loc, Val, 11, Type);
     writeMicroRelocation16<E>(Loc, Val, 10, 1);
     break;
   case R_MICROMIPS_PC16_S1:
-    checkInt<17>(Loc, Val, Type);
+    checkInt(Loc, Val, 17, Type);
     writeShuffleValue<E>(Loc, Val, 16, 1);
     break;
   case R_MICROMIPS_PC18_S3:
-    checkInt<21>(Loc, Val, Type);
+    checkInt(Loc, Val, 21, Type);
     writeShuffleValue<E>(Loc, Val, 18, 3);
     break;
   case R_MICROMIPS_PC19_S2:
-    checkInt<21>(Loc, Val, Type);
+    checkInt(Loc, Val, 21, Type);
     writeShuffleValue<E>(Loc, Val, 19, 2);
     break;
   case R_MICROMIPS_PC21_S1:
-    checkInt<22>(Loc, Val, Type);
+    checkInt(Loc, Val, 22, Type);
     writeShuffleValue<E>(Loc, Val, 21, 1);
     break;
   case R_MICROMIPS_PC23_S2:
-    checkInt<25>(Loc, Val, Type);
+    checkInt(Loc, Val, 25, Type);
     writeShuffleValue<E>(Loc, Val, 23, 2);
     break;
   default:
diff --git a/ELF/Arch/PPC.cpp b/ELF/Arch/PPC.cpp
index 6af0df3..20cae0e 100644
--- a/ELF/Arch/PPC.cpp
+++ b/ELF/Arch/PPC.cpp
@@ -21,13 +21,18 @@
 namespace {
 class PPC final : public TargetInfo {
 public:
-  PPC() { GotBaseSymOff = 0x8000; }
+  PPC();
   void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
   RelExpr getRelExpr(RelType Type, const Symbol &S,
                      const uint8_t *Loc) const override;
 };
 } // namespace
 
+PPC::PPC() {
+  GotBaseSymOff = 0x8000;
+  GotBaseSymInGotPlt = false;
+}
+
 RelExpr PPC::getRelExpr(RelType Type, const Symbol &S,
                         const uint8_t *Loc) const {
   switch (Type) {
diff --git a/ELF/Arch/PPC64.cpp b/ELF/Arch/PPC64.cpp
index ac4021b..d3c2dbd 100644
--- a/ELF/Arch/PPC64.cpp
+++ b/ELF/Arch/PPC64.cpp
@@ -14,6 +14,7 @@
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
+using namespace llvm::object;
 using namespace llvm::support::endian;
 using namespace llvm::ELF;
 using namespace lld;
@@ -39,11 +40,13 @@
 class PPC64 final : public TargetInfo {
 public:
   PPC64();
+  uint32_t calcEFlags() const override;
   RelExpr getRelExpr(RelType Type, const Symbol &S,
                      const uint8_t *Loc) const override;
   void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
                 int32_t Index, unsigned RelOff) const override;
   void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+  void writeGotHeader(uint8_t *Buf) const override;
 };
 } // namespace
 
@@ -66,6 +69,10 @@
   GotPltEntrySize = 8;
   PltEntrySize = 32;
   PltHeaderSize = 0;
+  GotBaseSymInGotPlt = false;
+  GotBaseSymOff = 0x8000;
+  if (Config->EKind == ELF64LEKind)
+    GotHeaderEntriesNum = 1;
 
   // We need 64K pages (at least under glibc/Linux, the loader won't
   // set different permissions on a finer granularity than that).
@@ -82,6 +89,42 @@
   DefaultImageBase = 0x10000000;
 }
 
+static uint32_t getEFlags(InputFile *File) {
+  // Get the e_flag from the input file and if it is unspecified, then set it to
+  // the e_flag appropriate for the ABI.
+
+  // We are currently handling both ELF64LE and ELF64BE but eventually will
+  // remove BE support once v2 ABI support is complete.
+  switch (Config->EKind) {
+  case ELF64BEKind:
+    if (uint32_t EFlags =
+        cast<ObjFile<ELF64BE>>(File)->getObj().getHeader()->e_flags)
+      return EFlags;
+    return 1;
+  case ELF64LEKind:
+    if (uint32_t EFlags =
+        cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags)
+      return EFlags;
+    return 2;
+  default:
+    llvm_unreachable("unknown Config->EKind");
+  }
+}
+
+uint32_t PPC64::calcEFlags() const {
+  assert(!ObjectFiles.empty());
+  uint32_t Ret = getEFlags(ObjectFiles[0]);
+
+  // Verify that all input files have the same e_flags.
+  for (InputFile *F : makeArrayRef(ObjectFiles).slice(1)) {
+    if (Ret == getEFlags(F))
+      continue;
+    error("incompatible e_flags: " + toString(F));
+    return 0;
+  }
+  return Ret;
+}
+
 RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
                           const uint8_t *Loc) const {
   switch (Type) {
@@ -96,11 +139,19 @@
     return R_PPC_TOC;
   case R_PPC64_REL24:
     return R_PPC_PLT_OPD;
+  case R_PPC64_REL16_LO:
+  case R_PPC64_REL16_HA:
+    return R_PC;
   default:
     return R_ABS;
   }
 }
 
+void PPC64::writeGotHeader(uint8_t *Buf) const {
+  if (Config->EKind == ELF64LEKind)
+    write64(Buf, getPPC64TocBase());
+}
+
 void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
                      uint64_t PltEntryAddr, int32_t Index,
                      unsigned RelOff) const {
@@ -112,14 +163,14 @@
   // be a pointer to the function descriptor in the .opd section. Using
   // this scheme is simpler, but requires an extra indirection per PLT dispatch.
 
-  write32be(Buf, 0xf8410028);                       // std %r2, 40(%r1)
-  write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
-  write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
-  write32be(Buf + 12, 0xe96c0000);                  // ld %r11,0(%r12)
-  write32be(Buf + 16, 0x7d6903a6);                  // mtctr %r11
-  write32be(Buf + 20, 0xe84c0008);                  // ld %r2,8(%r12)
-  write32be(Buf + 24, 0xe96c0010);                  // ld %r11,16(%r12)
-  write32be(Buf + 28, 0x4e800420);                  // bctr
+  write32(Buf, 0xf8410028);                       // std %r2, 40(%r1)
+  write32(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
+  write32(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
+  write32(Buf + 12, 0xe96c0000);                  // ld %r11,0(%r12)
+  write32(Buf + 16, 0x7d6903a6);                  // mtctr %r11
+  write32(Buf + 20, 0xe84c0008);                  // ld %r2,8(%r12)
+  write32(Buf + 24, 0xe96c0010);                  // ld %r11,16(%r12)
+  write32(Buf + 28, 0x4e800420);                  // bctr
 }
 
 static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) {
@@ -149,61 +200,61 @@
 
   switch (Type) {
   case R_PPC64_ADDR14: {
-    checkAlignment<4>(Loc, Val, Type);
+    checkAlignment(Loc, Val, 4, Type);
     // Preserve the AA/LK bits in the branch instruction
     uint8_t AALK = Loc[3];
-    write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc));
+    write16(Loc + 2, (AALK & 3) | (Val & 0xfffc));
     break;
   }
   case R_PPC64_ADDR16:
-    checkInt<16>(Loc, Val, Type);
-    write16be(Loc, Val);
+    checkInt(Loc, Val, 16, Type);
+    write16(Loc, Val);
     break;
   case R_PPC64_ADDR16_DS:
-    checkInt<16>(Loc, Val, Type);
-    write16be(Loc, (read16be(Loc) & 3) | (Val & ~3));
+    checkInt(Loc, Val, 16, Type);
+    write16(Loc, (read16(Loc) & 3) | (Val & ~3));
     break;
   case R_PPC64_ADDR16_HA:
   case R_PPC64_REL16_HA:
-    write16be(Loc, applyPPCHa(Val));
+    write16(Loc, applyPPCHa(Val));
     break;
   case R_PPC64_ADDR16_HI:
   case R_PPC64_REL16_HI:
-    write16be(Loc, applyPPCHi(Val));
+    write16(Loc, applyPPCHi(Val));
     break;
   case R_PPC64_ADDR16_HIGHER:
-    write16be(Loc, applyPPCHigher(Val));
+    write16(Loc, applyPPCHigher(Val));
     break;
   case R_PPC64_ADDR16_HIGHERA:
-    write16be(Loc, applyPPCHighera(Val));
+    write16(Loc, applyPPCHighera(Val));
     break;
   case R_PPC64_ADDR16_HIGHEST:
-    write16be(Loc, applyPPCHighest(Val));
+    write16(Loc, applyPPCHighest(Val));
     break;
   case R_PPC64_ADDR16_HIGHESTA:
-    write16be(Loc, applyPPCHighesta(Val));
+    write16(Loc, applyPPCHighesta(Val));
     break;
   case R_PPC64_ADDR16_LO:
-    write16be(Loc, applyPPCLo(Val));
+  case R_PPC64_REL16_LO:
+    write16(Loc, applyPPCLo(Val));
     break;
   case R_PPC64_ADDR16_LO_DS:
-  case R_PPC64_REL16_LO:
-    write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(Val) & ~3));
+    write16(Loc, (read16(Loc) & 3) | (applyPPCLo(Val) & ~3));
     break;
   case R_PPC64_ADDR32:
   case R_PPC64_REL32:
-    checkInt<32>(Loc, Val, Type);
-    write32be(Loc, Val);
+    checkInt(Loc, Val, 32, Type);
+    write32(Loc, Val);
     break;
   case R_PPC64_ADDR64:
   case R_PPC64_REL64:
   case R_PPC64_TOC:
-    write64be(Loc, Val);
+    write64(Loc, Val);
     break;
   case R_PPC64_REL24: {
     uint32_t Mask = 0x03FFFFFC;
-    checkInt<24>(Loc, Val, Type);
-    write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask));
+    checkInt(Loc, Val, 24, Type);
+    write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
     break;
   }
   default:
diff --git a/ELF/Arch/SPARCV9.cpp b/ELF/Arch/SPARCV9.cpp
index d9d6e13..36f5c83 100644
--- a/ELF/Arch/SPARCV9.cpp
+++ b/ELF/Arch/SPARCV9.cpp
@@ -77,23 +77,23 @@
   case R_SPARC_32:
   case R_SPARC_UA32:
     // V-word32
-    checkUInt<32>(Loc, Val, Type);
+    checkUInt(Loc, Val, 32, Type);
     write32be(Loc, Val);
     break;
   case R_SPARC_DISP32:
     // V-disp32
-    checkInt<32>(Loc, Val, Type);
+    checkInt(Loc, Val, 32, Type);
     write32be(Loc, Val);
     break;
   case R_SPARC_WDISP30:
   case R_SPARC_WPLT30:
     // V-disp30
-    checkInt<32>(Loc, Val, Type);
+    checkInt(Loc, Val, 32, Type);
     write32be(Loc, (read32be(Loc) & ~0x3fffffff) | ((Val >> 2) & 0x3fffffff));
     break;
   case R_SPARC_22:
     // V-imm22
-    checkUInt<22>(Loc, Val, Type);
+    checkUInt(Loc, Val, 22, Type);
     write32be(Loc, (read32be(Loc) & ~0x003fffff) | (Val & 0x003fffff));
     break;
   case R_SPARC_GOT22:
@@ -103,7 +103,7 @@
     break;
   case R_SPARC_WDISP19:
     // V-disp19
-    checkInt<21>(Loc, Val, Type);
+    checkInt(Loc, Val, 21, Type);
     write32be(Loc, (read32be(Loc) & ~0x0007ffff) | ((Val >> 2) & 0x0007ffff));
     break;
   case R_SPARC_GOT10:
@@ -137,7 +137,7 @@
   };
   memcpy(Buf, PltData, sizeof(PltData));
 
-  uint64_t Off = PltHeaderSize + Index * PltEntrySize;
+  uint64_t Off = getPltEntryOffset(Index);
   relocateOne(Buf, R_SPARC_22, Off);
   relocateOne(Buf + 4, R_SPARC_WDISP19, -(Off + 4 - PltEntrySize));
 }
diff --git a/ELF/Arch/X86.cpp b/ELF/Arch/X86.cpp
index 09c16db..87c84ad 100644
--- a/ELF/Arch/X86.cpp
+++ b/ELF/Arch/X86.cpp
@@ -46,7 +46,6 @@
 } // namespace
 
 X86::X86() {
-  GotBaseSymOff = -1;
   CopyRel = R_386_COPY;
   GotRel = R_386_GLOB_DAT;
   PltRel = R_386_JUMP_SLOT;
@@ -224,7 +223,7 @@
   }
 
   write32le(Buf + 7, RelOff);
-  write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
+  write32le(Buf + 12, -getPltEntryOffset(Index) - 16);
 }
 
 int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const {
@@ -256,15 +255,15 @@
     // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are
     // being used for some 16-bit programs such as boot loaders, so
     // we want to support them.
-    checkUInt<8>(Loc, Val, Type);
+    checkUInt(Loc, Val, 8, Type);
     *Loc = Val;
     break;
   case R_386_PC8:
-    checkInt<8>(Loc, Val, Type);
+    checkInt(Loc, Val, 8, Type);
     *Loc = Val;
     break;
   case R_386_16:
-    checkUInt<16>(Loc, Val, Type);
+    checkUInt(Loc, Val, 16, Type);
     write16le(Loc, Val);
     break;
   case R_386_PC16:
@@ -278,7 +277,7 @@
     // current location subtracted from it.
     // We just check that Val fits in 17 bits. This misses some cases, but
     // should have no false positives.
-    checkInt<17>(Loc, Val, Type);
+    checkInt(Loc, Val, 17, Type);
     write16le(Loc, Val);
     break;
   case R_386_32:
@@ -301,7 +300,7 @@
   case R_386_TLS_LE_32:
   case R_386_TLS_TPOFF:
   case R_386_TLS_TPOFF32:
-    checkInt<32>(Loc, Val, Type);
+    checkInt(Loc, Val, 32, Type);
     write32le(Loc, Val);
     break;
   default:
@@ -444,6 +443,7 @@
       0x89, 0xc8,                               // 2b:   mov %ecx, %eax
       0x59,                                     // 2d:   pop %ecx
       0xc3,                                     // 2e:   ret
+      0xcc,                                     // 2f:   int3; padding
   };
   memcpy(Buf, Insn, sizeof(Insn));
 
@@ -457,21 +457,23 @@
                             uint64_t PltEntryAddr, int32_t Index,
                             unsigned RelOff) const {
   const uint8_t Insn[] = {
-      0x50,                   // pushl %eax
-      0x8b, 0x83, 0, 0, 0, 0, // mov foo@GOT(%ebx), %eax
-      0xe8, 0,    0, 0, 0,    // call plt+0x20
-      0xe9, 0,    0, 0, 0,    // jmp plt+0x12
-      0x68, 0,    0, 0, 0,    // pushl $reloc_offset
-      0xe9, 0,    0, 0, 0,    // jmp plt+0
+      0x50,                            // pushl %eax
+      0x8b, 0x83, 0,    0,    0,    0, // mov foo@GOT(%ebx), %eax
+      0xe8, 0,    0,    0,    0,       // call plt+0x20
+      0xe9, 0,    0,    0,    0,       // jmp plt+0x12
+      0x68, 0,    0,    0,    0,       // pushl $reloc_offset
+      0xe9, 0,    0,    0,    0,       // jmp plt+0
+      0xcc, 0xcc, 0xcc, 0xcc, 0xcc,    // int3; padding
   };
   memcpy(Buf, Insn, sizeof(Insn));
 
   uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize();
+  unsigned Off = getPltEntryOffset(Index);
   write32le(Buf + 3, GotPltEntryAddr - Ebx);
-  write32le(Buf + 8, -Index * PltEntrySize - PltHeaderSize - 12 + 32);
-  write32le(Buf + 13, -Index * PltEntrySize - PltHeaderSize - 17 + 18);
+  write32le(Buf + 8, -Off - 12 + 32);
+  write32le(Buf + 13, -Off - 17 + 18);
   write32le(Buf + 18, RelOff);
-  write32le(Buf + 23, -Index * PltEntrySize - PltHeaderSize - 27);
+  write32le(Buf + 23, -Off - 27);
 }
 
 RetpolineNoPic::RetpolineNoPic() {
@@ -484,7 +486,7 @@
 }
 
 void RetpolineNoPic::writePltHeader(uint8_t *Buf) const {
-  const uint8_t PltData[] = {
+  const uint8_t Insn[] = {
       0xff, 0x35, 0,    0,    0,    0, // 0:    pushl GOTPLT+4
       0x50,                            // 6:    pushl %eax
       0xa1, 0,    0,    0,    0,       // 7:    mov GOTPLT+8, %eax
@@ -500,8 +502,9 @@
       0x89, 0xc8,                      // 2b:   mov %ecx, %eax
       0x59,                            // 2d:   pop %ecx
       0xc3,                            // 2e:   ret
+      0xcc,                            // 2f:   int3; padding
   };
-  memcpy(Buf, PltData, sizeof(PltData));
+  memcpy(Buf, Insn, sizeof(Insn));
 
   uint32_t GotPlt = InX::GotPlt->getVA();
   write32le(Buf + 2, GotPlt + 4);
@@ -512,20 +515,23 @@
                               uint64_t PltEntryAddr, int32_t Index,
                               unsigned RelOff) const {
   const uint8_t Insn[] = {
-      0x50,             // 0:  pushl %eax
-      0xa1, 0, 0, 0, 0, // 1:  mov foo_in_GOT, %eax
-      0xe8, 0, 0, 0, 0, // 6:  call plt+0x20
-      0xe9, 0, 0, 0, 0, // b:  jmp plt+0x11
-      0x68, 0, 0, 0, 0, // 10: pushl $reloc_offset
-      0xe9, 0, 0, 0, 0, // 15: jmp plt+0
+      0x50,                         // 0:  pushl %eax
+      0xa1, 0,    0,    0,    0,    // 1:  mov foo_in_GOT, %eax
+      0xe8, 0,    0,    0,    0,    // 6:  call plt+0x20
+      0xe9, 0,    0,    0,    0,    // b:  jmp plt+0x11
+      0x68, 0,    0,    0,    0,    // 10: pushl $reloc_offset
+      0xe9, 0,    0,    0,    0,    // 15: jmp plt+0
+      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding
+      0xcc,                         // 1f: int3; padding
   };
   memcpy(Buf, Insn, sizeof(Insn));
 
+  unsigned Off = getPltEntryOffset(Index);
   write32le(Buf + 2, GotPltEntryAddr);
-  write32le(Buf + 7, -Index * PltEntrySize - PltHeaderSize - 11 + 32);
-  write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16 + 17);
+  write32le(Buf + 7, -Off - 11 + 32);
+  write32le(Buf + 12, -Off - 16 + 17);
   write32le(Buf + 17, RelOff);
-  write32le(Buf + 22, -Index * PltEntrySize - PltHeaderSize - 26);
+  write32le(Buf + 22, -Off - 26);
 }
 
 TargetInfo *elf::getX86TargetInfo() {
diff --git a/ELF/Arch/X86_64.cpp b/ELF/Arch/X86_64.cpp
index 3db391e..a370508 100644
--- a/ELF/Arch/X86_64.cpp
+++ b/ELF/Arch/X86_64.cpp
@@ -51,7 +51,6 @@
 } // namespace
 
 template <class ELFT> X86_64<ELFT>::X86_64() {
-  GotBaseSymOff = -1;
   CopyRel = R_X86_64_COPY;
   GotRel = R_X86_64_GLOB_DAT;
   PltRel = R_X86_64_JUMP_SLOT;
@@ -153,7 +152,7 @@
 
   write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);
   write32le(Buf + 7, Index);
-  write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
+  write32le(Buf + 12, -getPltEntryOffset(Index) - 16);
 }
 
 template <class ELFT> bool X86_64<ELFT>::isPicRel(RelType Type) const {
@@ -285,15 +284,15 @@
 void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
   switch (Type) {
   case R_X86_64_8:
-    checkUInt<8>(Loc, Val, Type);
+    checkUInt(Loc, Val, 8, Type);
     *Loc = Val;
     break;
   case R_X86_64_16:
-    checkUInt<16>(Loc, Val, Type);
+    checkUInt(Loc, Val, 16, Type);
     write16le(Loc, Val);
     break;
   case R_X86_64_32:
-    checkUInt<32>(Loc, Val, Type);
+    checkUInt(Loc, Val, 32, Type);
     write32le(Loc, Val);
     break;
   case R_X86_64_32S:
@@ -309,7 +308,7 @@
   case R_X86_64_TLSLD:
   case R_X86_64_DTPOFF32:
   case R_X86_64_SIZE32:
-    checkInt<32>(Loc, Val, Type);
+    checkInt(Loc, Val, 32, Type);
     write32le(Loc, Val);
     break;
   case R_X86_64_64:
@@ -501,6 +500,8 @@
       0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 19:   int3; .align 16
       0x4c, 0x89, 0x1c, 0x24,                   // 20: next: mov %r11, (%rsp)
       0xc3,                                     // 24:   ret
+      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25:   int3; padding
+      0xcc, 0xcc, 0xcc, 0xcc,                   // 2c:   int3; padding
   };
   memcpy(Buf, Insn, sizeof(Insn));
 
@@ -516,14 +517,15 @@
                                unsigned RelOff) const {
   const uint8_t Insn[] = {
       0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0:  mov foo@GOTPLT(%rip), %r11
-      0xe8, 0,    0,    0, 0,       // 7:  callq plt+0x20
-      0xe9, 0,    0,    0, 0,       // c:  jmp plt+0x12
-      0x68, 0,    0,    0, 0,       // 11: pushq <relocation index>
-      0xe9, 0,    0,    0, 0,       // 16: jmp plt+0
+      0xe8, 0,    0,    0,    0,    // 7:  callq plt+0x20
+      0xe9, 0,    0,    0,    0,    // c:  jmp plt+0x12
+      0x68, 0,    0,    0,    0,    // 11: pushq <relocation index>
+      0xe9, 0,    0,    0,    0,    // 16: jmp plt+0
+      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding
   };
   memcpy(Buf, Insn, sizeof(Insn));
 
-  uint64_t Off = TargetInfo::PltHeaderSize + TargetInfo::PltEntrySize * Index;
+  uint64_t Off = TargetInfo::getPltEntryOffset(Index);
 
   write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
   write32le(Buf + 8, -Off - 12 + 32);
@@ -547,6 +549,9 @@
       0xcc, 0xcc, 0xcc, 0xcc,       // c:    int3; .align 16
       0x4c, 0x89, 0x1c, 0x24,       // 10: next: mov %r11, (%rsp)
       0xc3,                         // 14:   ret
+      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 15:   int3; padding
+      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a:   int3; padding
+      0xcc,                         // 1f:   int3; padding
   };
   memcpy(Buf, Insn, sizeof(Insn));
 }
@@ -556,14 +561,14 @@
                                    uint64_t PltEntryAddr, int32_t Index,
                                    unsigned RelOff) const {
   const uint8_t Insn[] = {
-      0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // mov foo@GOTPLT(%rip), %r11
-      0xe9, 0,    0,    0, 0,       // jmp plt+0
+      0x4c, 0x8b, 0x1d, 0,    0, 0, 0, // mov foo@GOTPLT(%rip), %r11
+      0xe9, 0,    0,    0,    0,       // jmp plt+0
+      0xcc, 0xcc, 0xcc, 0xcc,          // int3; padding
   };
   memcpy(Buf, Insn, sizeof(Insn));
 
   write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
-  write32le(Buf + 8,
-            -Index * TargetInfo::PltEntrySize - TargetInfo::PltHeaderSize - 12);
+  write32le(Buf + 8, -TargetInfo::getPltEntryOffset(Index) - 12);
 }
 
 template <class ELFT> TargetInfo *getTargetInfo() {
diff --git a/ELF/Config.h b/ELF/Config.h
index 193a520..2007992 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -113,6 +113,7 @@
   bool BsymbolicFunctions;
   bool CheckSections;
   bool CompressDebugSections;
+  bool Cref;
   bool DefineCommon;
   bool Demangle = true;
   bool DisableVerify;
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 8abac81..4565fde 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -127,6 +127,7 @@
           .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})
@@ -600,6 +601,17 @@
   return Names.takeVector();
 }
 
+static void parseClangOption(StringRef Opt, const Twine &Msg) {
+  std::string Err;
+  raw_string_ostream OS(Err);
+
+  const char *Argv[] = {Config->ProgName.data(), Opt.data()};
+  if (cl::ParseCommandLineOptions(2, Argv, "", &OS))
+    return;
+  OS.flush();
+  error(Msg + ": " + StringRef(Err).trim());
+}
+
 // Initializes Config members by the command line options.
 void LinkerDriver::readConfigs(opt::InputArgList &Args) {
   errorHandler().Verbose = Args.hasArg(OPT_verbose);
@@ -617,6 +629,7 @@
       Args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);
   Config->Chroot = Args.getLastArgValue(OPT_chroot);
   Config->CompressDebugSections = getCompressDebugSections(Args);
+  Config->Cref = Args.hasFlag(OPT_cref, OPT_no_cref, false);
   Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common,
                                       !Args.hasArg(OPT_relocatable));
   Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
@@ -707,7 +720,6 @@
   Config->ZWxneeded = hasZOption(Args, "wxneeded");
 
   // Parse LTO plugin-related options for compatibility with gold.
-  std::vector<const char *> LTOOptions({Config->ProgName.data()});
   for (auto *Arg : Args.filtered(OPT_plugin_opt)) {
     StringRef S = Arg->getValue();
     if (S == "disable-verify")
@@ -721,15 +733,15 @@
     else if (S.startswith("jobs="))
       Config->ThinLTOJobs = parseInt(S.substr(5), Arg);
     else if (S.startswith("mcpu="))
-      LTOOptions.push_back(Saver.save("-" + S).data());
+      parseClangOption(Saver.save("-" + S), Arg->getSpelling());
     else if (!S.startswith("/") && !S.startswith("-fresolution=") &&
              !S.startswith("-pass-through=") && !S.startswith("thinlto"))
-      LTOOptions.push_back(S.data());
+      parseClangOption(S, Arg->getSpelling());
   }
-  // Parse and evaluate -mllvm options.
+
+  // Parse -mllvm options.
   for (auto *Arg : Args.filtered(OPT_mllvm))
-    LTOOptions.push_back(Arg->getValue());
-  cl::ParseCommandLineOptions(LTOOptions.size(), LTOOptions.data());
+    parseClangOption(Arg->getValue(), Arg->getSpelling());
 
   if (Config->LTOO > 3)
     error("invalid optimization level for LTO: " + Twine(Config->LTOO));
@@ -910,6 +922,12 @@
     case OPT_no_whole_archive:
       InWholeArchive = false;
       break;
+    case OPT_just_symbols:
+      if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) {
+        Files.push_back(createObjectFile(*MB));
+        Files.back()->JustSymbols = true;
+      }
+      break;
     case OPT_start_lib:
       InLib = true;
       break;
@@ -1081,6 +1099,10 @@
   if (errorCount())
     return;
 
+  // Now when we read all script files, we want to finalize order of linker
+  // script commands, which can be not yet final because of INSERT commands.
+  Script->processInsertCommands();
+
   // We want to declare linker script's symbols early,
   // so that we can version them.
   // They also might be exported if referenced by DSOs.
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp
index 8b58c99..ffd6029 100644
--- a/ELF/ICF.cpp
+++ b/ELF/ICF.cpp
@@ -77,6 +77,7 @@
 #include "Config.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
+#include "SyntheticSections.h"
 #include "lld/Common/Threads.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/BinaryFormat/ELF.h"
@@ -161,16 +162,26 @@
 
 // Returns true if section S is subject of ICF.
 static bool isEligible(InputSection *S) {
+  if (!S->Live || !(S->Flags & SHF_ALLOC) || (S->Flags & SHF_WRITE))
+    return false;
+
   // Don't merge read only data sections unless
   // --ignore-data-address-equality was passed.
   if (!(S->Flags & SHF_EXECINSTR) && !Config->IgnoreDataAddressEquality)
     return false;
 
-  // .init and .fini contains instructions that must be executed to
-  // initialize and finalize the process. They cannot and should not
-  // be merged.
-  return S->Live && (S->Flags & SHF_ALLOC) && !(S->Flags & SHF_WRITE) &&
-         S->Name != ".init" && S->Name != ".fini";
+  // Don't merge synthetic sections as their Data member is not valid and empty.
+  // The Data member needs to be valid for ICF as it is used by ICF to determine
+  // the equality of section contents.
+  if (isa<SyntheticSection>(S))
+    return false;
+
+  // .init and .fini contains instructions that must be executed to initialize
+  // and finalize the process. They cannot and should not be merged.
+  if (S->Name == ".init" || S->Name == ".fini")
+    return false;
+
+  return true;
 }
 
 // Split an equivalence class into smaller classes.
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 0bff035..bb20c83 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -115,49 +115,46 @@
 }
 
 template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
-  DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(this));
-  const DWARFObject &Obj = Dwarf.getDWARFObj();
+  Dwarf = llvm::make_unique<DWARFContext>(make_unique<LLDDwarfObj<ELFT>>(this));
+  const DWARFObject &Obj = Dwarf->getDWARFObj();
   DwarfLine.reset(new DWARFDebugLine);
   DWARFDataExtractor LineData(Obj, Obj.getLineSection(), Config->IsLE,
                               Config->Wordsize);
 
-  // The second parameter is offset in .debug_line section
-  // for compilation unit (CU) of interest. We have only one
-  // CU (object file), so offset is always 0.
-  const DWARFDebugLine::LineTable *LT =
-      DwarfLine->getOrParseLineTable(LineData, 0, Dwarf, nullptr);
-
-  // Return if there is no debug information about CU available.
-  if (!Dwarf.getNumCompileUnits())
-    return;
-
-  // Loop over variable records and insert them to VariableLoc.
-  DWARFCompileUnit *CU = Dwarf.getCompileUnitAtIndex(0);
-  for (const auto &Entry : CU->dies()) {
-    DWARFDie Die(CU, &Entry);
-    // Skip all tags that are not variables.
-    if (Die.getTag() != dwarf::DW_TAG_variable)
+  for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf->compile_units()) {
+    const DWARFDebugLine::LineTable *LT = Dwarf->getLineTableForUnit(CU.get());
+    if (!LT)
       continue;
+    LineTables.push_back(LT);
 
-    // Skip if a local variable because we don't need them for generating error
-    // messages. In general, only non-local symbols can fail to be linked.
-    if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))
-      continue;
+    // Loop over variable records and insert them to VariableLoc.
+    for (const auto &Entry : CU->dies()) {
+      DWARFDie Die(CU.get(), &Entry);
+      // Skip all tags that are not variables.
+      if (Die.getTag() != dwarf::DW_TAG_variable)
+        continue;
 
-    // Get the source filename index for the variable.
-    unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);
-    if (!LT->hasFileAtIndex(File))
-      continue;
+      // Skip if a local variable because we don't need them for generating
+      // error messages. In general, only non-local symbols can fail to be
+      // linked.
+      if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))
+        continue;
 
-    // Get the line number on which the variable is declared.
-    unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);
+      // Get the source filename index for the variable.
+      unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);
+      if (!LT->hasFileAtIndex(File))
+        continue;
 
-    // Get the name of the variable and add the collected information to
-    // VariableLoc. Usually Name is non-empty, but it can be empty if the input
-    // object file lacks some debug info.
-    StringRef Name = dwarf::toString(Die.find(dwarf::DW_AT_name), "");
-    if (!Name.empty())
-      VariableLoc.insert({Name, {File, Line}});
+      // Get the line number on which the variable is declared.
+      unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);
+
+      // Get the name of the variable and add the collected information to
+      // VariableLoc. Usually Name is non-empty, but it can be empty if the
+      // input object file lacks some debug info.
+      StringRef Name = dwarf::toString(Die.find(dwarf::DW_AT_name), "");
+      if (!Name.empty())
+        VariableLoc.insert({Name, {LT, File, Line}});
+    }
   }
 }
 
@@ -168,11 +165,6 @@
 ObjFile<ELFT>::getVariableLoc(StringRef Name) {
   llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
 
-  // There is always only one CU so it's offset is 0.
-  const DWARFDebugLine::LineTable *LT = DwarfLine->getLineTable(0);
-  if (!LT)
-    return None;
-
   // Return if we have no debug information about data object.
   auto It = VariableLoc.find(Name);
   if (It == VariableLoc.end())
@@ -180,12 +172,12 @@
 
   // Take file name string from line table.
   std::string FileName;
-  if (!LT->getFileNameByIndex(
-          It->second.first /* File */, nullptr,
+  if (!It->second.LT->getFileNameByIndex(
+          It->second.File, nullptr,
           DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName))
     return None;
 
-  return std::make_pair(FileName, It->second.second /*Line*/);
+  return std::make_pair(FileName, It->second.Line);
 }
 
 // Returns source line information for a given offset
@@ -195,24 +187,18 @@
                                                   uint64_t Offset) {
   llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
 
-  // The offset to CU is 0.
-  const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0);
-  if (!Tbl)
-    return None;
-
   // Use fake address calcuated by adding section file offset and offset in
   // section. See comments for ObjectInfo class.
   DILineInfo Info;
-  Tbl->getFileLineInfoForAddress(
-      S->getOffsetInFile() + Offset, nullptr,
-      DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info);
-  if (Info.Line == 0)
-    return None;
-  return Info;
+  for (const llvm::DWARFDebugLine::LineTable *LT : LineTables)
+    if (LT->getFileLineInfoForAddress(
+            S->getOffsetInFile() + Offset, nullptr,
+            DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info))
+      return Info;
+  return None;
 }
 
-// Returns source line information for a given offset
-// using DWARF debug info.
+// Returns source line information for a given offset using DWARF debug info.
 template <class ELFT>
 std::string ObjFile<ELFT>::getLineInfo(InputSectionBase *S, uint64_t Offset) {
   if (Optional<DILineInfo> Info = getDILineInfo(S, Offset))
@@ -247,7 +233,7 @@
 
 template <class ELFT>
 typename ELFT::SymRange ELFFileBase<ELFT>::getGlobalELFSyms() {
-  return makeArrayRef(ELFSyms.begin() + FirstNonLocal, ELFSyms.end());
+  return makeArrayRef(ELFSyms.begin() + FirstGlobal, ELFSyms.end());
 }
 
 template <class ELFT>
@@ -258,9 +244,9 @@
 template <class ELFT>
 void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections,
                                    const Elf_Shdr *Symtab) {
-  FirstNonLocal = Symtab->sh_info;
+  FirstGlobal = Symtab->sh_info;
   ELFSyms = CHECK(getObj().symbols(Symtab), this);
-  if (FirstNonLocal == 0 || FirstNonLocal > ELFSyms.size())
+  if (FirstGlobal == 0 || FirstGlobal > ELFSyms.size())
     fatal(toString(this) + ": invalid sh_info in symbol table");
 
   StringTable =
@@ -276,13 +262,22 @@
 template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getLocalSymbols() {
   if (this->Symbols.empty())
     return {};
-  return makeArrayRef(this->Symbols).slice(1, this->FirstNonLocal - 1);
+  return makeArrayRef(this->Symbols).slice(1, this->FirstGlobal - 1);
+}
+
+template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getGlobalSymbols() {
+  return makeArrayRef(this->Symbols).slice(this->FirstGlobal);
 }
 
 template <class ELFT>
 void ObjFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {
-  // Read section and symbol tables.
-  initializeSections(ComdatGroups);
+  // Read a section table. JustSymbols is usually false.
+  if (this->JustSymbols)
+    initializeJustSymbols();
+  else
+    initializeSections(ComdatGroups);
+
+  // Read a symbol table.
   initializeSymbols();
 }
 
@@ -306,7 +301,7 @@
   // we use a section name as a signature.
   //
   // Such SHT_GROUP sections are invalid from the perspective of the ELF
-  // standard, but GNU gold 1.14 (the neweset version as of July 2017) or
+  // standard, but GNU gold 1.14 (the newest version as of July 2017) or
   // older produce such sections as outputs for the -r option, so we need
   // a bug-compatibility.
   if (Signature.empty() && Sym->getType() == STT_SECTION)
@@ -326,9 +321,19 @@
 }
 
 template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
-  // We don't merge sections if -O0 (default is -O1). This makes sometimes
-  // the linker significantly faster, although the output will be bigger.
-  if (Config->Optimize == 0)
+  // On a regular link we don't merge sections if -O0 (default is -O1). This
+  // sometimes makes the linker significantly faster, although the output will
+  // be bigger.
+  //
+  // Doing the same for -r would create a problem as it would combine sections
+  // with different sh_entsize. One option would be to just copy every SHF_MERGE
+  // section as is to the output. While this would produce a valid ELF file with
+  // usable SHF_MERGE sections, tools like (llvm-)?dwarfdump get confused when
+  // they see two .debug_str. We could have separate logic for combining
+  // SHF_MERGE sections based both on their name and sh_entsize, but that seems
+  // to be more trouble than it is worth. Instead, we just use the regular (-O1)
+  // logic for -r.
+  if (Config->Optimize == 0 && !Config->Relocatable)
     return false;
 
   // A mergeable section with size 0 is useless because they don't have
@@ -359,6 +364,27 @@
   return true;
 }
 
+// This is for --just-symbols.
+//
+// --just-symbols is a very minor feature that allows you to link your
+// output against other existing program, so that if you load both your
+// program and the other program into memory, your output can refer the
+// other program's symbols.
+//
+// When the option is given, we link "just symbols". The section table is
+// initialized with null pointers.
+template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
+  ArrayRef<Elf_Shdr> ObjSections = CHECK(this->getObj().sections(), this);
+  this->Sections.resize(ObjSections.size());
+
+  for (const Elf_Shdr &Sec : ObjSections) {
+    if (Sec.sh_type != SHT_SYMTAB)
+      continue;
+    this->initSymtab(ObjSections, &Sec);
+    return;
+  }
+}
+
 template <class ELFT>
 void ObjFile<ELFT>::initializeSections(
     DenseSet<CachedHashStringRef> &ComdatGroups) {
@@ -429,8 +455,15 @@
       if (Sec.sh_link >= this->Sections.size())
         fatal(toString(this) +
               ": invalid sh_link index: " + Twine(Sec.sh_link));
-      this->Sections[Sec.sh_link]->DependentSections.push_back(
-          cast<InputSection>(this->Sections[I]));
+
+      InputSectionBase *LinkSec = this->Sections[Sec.sh_link];
+      InputSection *IS = cast<InputSection>(this->Sections[I]);
+      LinkSec->DependentSections.push_back(IS);
+      if (!isa<InputSection>(LinkSec))
+        error("a section " + IS->Name +
+              " with SHF_LINK_ORDER should not refer a non-regular "
+              "section: " +
+              toString(LinkSec));
     }
   }
 }
@@ -525,10 +558,11 @@
   }
   case SHT_RELA:
   case SHT_REL: {
-    // Find the relocation target section and associate this
-    // section with it. Target can be discarded, for example
-    // if it is a duplicated member of SHT_GROUP section, we
-    // do not create or proccess relocatable sections then.
+    // Find a relocation target section and associate this section with that.
+    // Target may have been discarded if it is in a different section group
+    // and the group is discarded, even though it's a violation of the
+    // spec. We handle that situation gracefully by discarding dangling
+    // relocation sections.
     InputSectionBase *Target = getRelocTarget(Sec);
     if (!Target)
       return nullptr;
@@ -543,32 +577,28 @@
       fatal(toString(this) +
             ": multiple relocation sections to one section are not supported");
 
-    // Mergeable sections with relocations are tricky because relocations
-    // need to be taken into account when comparing section contents for
-    // merging. It's not worth supporting such mergeable sections because
-    // they are rare and it'd complicates the internal design (we usually
-    // have to determine if two sections are mergeable early in the link
-    // process much before applying relocations). We simply handle mergeable
-    // sections with relocations as non-mergeable.
+    // ELF spec allows mergeable sections with relocations, but they are
+    // rare, and it is in practice hard to merge such sections by contents,
+    // because applying relocations at end of linking changes section
+    // contents. So, we simply handle such sections as non-mergeable ones.
+    // Degrading like this is acceptable because section merging is optional.
     if (auto *MS = dyn_cast<MergeInputSection>(Target)) {
       Target = toRegularSection(MS);
       this->Sections[Sec.sh_info] = Target;
     }
 
-    size_t NumRelocations;
     if (Sec.sh_type == SHT_RELA) {
       ArrayRef<Elf_Rela> Rels = CHECK(this->getObj().relas(&Sec), this);
       Target->FirstRelocation = Rels.begin();
-      NumRelocations = Rels.size();
+      Target->NumRelocations = Rels.size();
       Target->AreRelocsRela = true;
     } else {
       ArrayRef<Elf_Rel> Rels = CHECK(this->getObj().rels(&Sec), this);
       Target->FirstRelocation = Rels.begin();
-      NumRelocations = Rels.size();
+      Target->NumRelocations = Rels.size();
       Target->AreRelocsRela = false;
     }
-    assert(isUInt<31>(NumRelocations));
-    Target->NumRelocations = NumRelocations;
+    assert(isUInt<31>(Target->NumRelocations));
 
     // Relocation sections processed by the linker are usually removed
     // from the output, so returning `nullptr` for the normal case.
@@ -789,34 +819,42 @@
   }
 }
 
+// Parses ".gnu.version" section which is a parallel array for the symbol table.
+// If a given file doesn't have ".gnu.version" section, returns VER_NDX_GLOBAL.
+template <class ELFT> std::vector<uint32_t> SharedFile<ELFT>::parseVersyms() {
+  size_t Size = this->ELFSyms.size() - this->FirstGlobal;
+  if (!VersymSec)
+    return std::vector<uint32_t>(Size, VER_NDX_GLOBAL);
+
+  const char *Base = this->MB.getBuffer().data();
+  const Elf_Versym *Versym =
+      reinterpret_cast<const Elf_Versym *>(Base + VersymSec->sh_offset) +
+      this->FirstGlobal;
+
+  std::vector<uint32_t> Ret(Size);
+  for (size_t I = 0; I < Size; ++I)
+    Ret[I] = Versym[I].vs_index;
+  return Ret;
+}
+
 // Parse the version definitions in the object file if present. Returns a vector
 // whose nth element contains a pointer to the Elf_Verdef for version identifier
-// n. Version identifiers that are not definitions map to nullptr. The array
-// always has at least length 1.
+// n. Version identifiers that are not definitions map to nullptr.
 template <class ELFT>
-std::vector<const typename ELFT::Verdef *>
-SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) {
-  std::vector<const Elf_Verdef *> Verdefs(1);
-  // We only need to process symbol versions for this DSO if it has both a
-  // versym and a verdef section, which indicates that the DSO contains symbol
-  // version definitions.
-  if (!VersymSec || !VerdefSec)
-    return Verdefs;
-
-  // The location of the first global versym entry.
-  const char *Base = this->MB.getBuffer().data();
-  Versym = reinterpret_cast<const Elf_Versym *>(Base + VersymSec->sh_offset) +
-           this->FirstNonLocal;
+std::vector<const typename ELFT::Verdef *> SharedFile<ELFT>::parseVerdefs() {
+  if (!VerdefSec)
+    return {};
 
   // We cannot determine the largest verdef identifier without inspecting
   // every Elf_Verdef, but both bfd and gold assign verdef identifiers
   // sequentially starting from 1, so we predict that the largest identifier
   // will be VerdefCount.
   unsigned VerdefCount = VerdefSec->sh_info;
-  Verdefs.resize(VerdefCount + 1);
+  std::vector<const Elf_Verdef *> Verdefs(VerdefCount + 1);
 
   // Build the Verdefs array by following the chain of Elf_Verdef objects
   // from the start of the .gnu.version_d section.
+  const char *Base = this->MB.getBuffer().data();
   const char *Verdef = Base + VerdefSec->sh_offset;
   for (unsigned I = 0; I != VerdefCount; ++I) {
     auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef);
@@ -830,24 +868,49 @@
   return Verdefs;
 }
 
-// Fully parse the shared object file. This must be called after parseSoName().
-template <class ELFT> void SharedFile<ELFT>::parseRest() {
-  // Create mapping from version identifiers to Elf_Verdef entries.
-  const Elf_Versym *Versym = nullptr;
-  Verdefs = parseVerdefs(Versym);
+// We do not usually care about alignments of data in shared object
+// files because the loader takes care of it. However, if we promote a
+// DSO symbol to point to .bss due to copy relocation, we need to keep
+// the original alignment requirements. We infer it in this function.
+template <class ELFT>
+uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections,
+                                        const Elf_Sym &Sym) {
+  uint64_t Ret = 1;
+  if (Sym.st_value)
+    Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value);
+  if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size())
+    Ret = std::min<uint64_t>(Ret, Sections[Sym.st_shndx].sh_addralign);
 
+  if (Ret > UINT32_MAX)
+    error(toString(this) + ": alignment too large: " +
+          CHECK(Sym.getName(this->StringTable), this));
+  return Ret;
+}
+
+// Fully parse the shared object file. This must be called after parseSoName().
+//
+// This function parses symbol versions. If a DSO has version information,
+// the file has a ".gnu.version_d" section which contains symbol version
+// definitions. Each symbol is associated to one version through a table in
+// ".gnu.version" section. That table is a parallel array for the symbol
+// table, and each table entry contains an index in ".gnu.version_d".
+//
+// The special index 0 is reserved for VERF_NDX_LOCAL and 1 is for
+// VER_NDX_GLOBAL. There's no table entry for these special versions in
+// ".gnu.version_d".
+//
+// The file format for symbol versioning is perhaps a bit more complicated
+// than necessary, but you can easily understand the code if you wrap your
+// head around the data structure described above.
+template <class ELFT> void SharedFile<ELFT>::parseRest() {
+  Verdefs = parseVerdefs();                       // parse .gnu.version_d
+  std::vector<uint32_t> Versyms = parseVersyms(); // parse .gnu.version
   ArrayRef<Elf_Shdr> Sections = CHECK(this->getObj().sections(), this);
 
   // Add symbols to the symbol table.
-  Elf_Sym_Range Syms = this->getGlobalELFSyms();
-  for (const Elf_Sym &Sym : Syms) {
-    unsigned VersymIndex = VER_NDX_GLOBAL;
-    if (Versym) {
-      VersymIndex = Versym->vs_index;
-      ++Versym;
-    }
-    bool Hidden = VersymIndex & VERSYM_HIDDEN;
-    VersymIndex = VersymIndex & ~VERSYM_HIDDEN;
+  ArrayRef<Elf_Sym> Syms = this->getGlobalELFSyms();
+  for (size_t I = 0; I < Syms.size(); ++I) {
+    const Elf_Sym &Sym = Syms[I];
 
     StringRef Name = CHECK(Sym.getName(this->StringTable), this);
     if (Sym.isUndefined()) {
@@ -858,57 +921,44 @@
       continue;
     }
 
+    // ELF spec requires that all local symbols precede weak or global
+    // symbols in each symbol table, and the index of first non-local symbol
+    // is stored to sh_info. If a local symbol appears after some non-local
+    // symbol, that's a violation of the spec.
     if (Sym.getBinding() == STB_LOCAL) {
       warn("found local symbol '" + Name +
            "' in global part of symbol table in file " + toString(this));
       continue;
     }
 
-    if (Config->EMachine == EM_MIPS) {
-      // FIXME: MIPS BFD linker puts _gp_disp symbol into DSO files
-      // and incorrectly assigns VER_NDX_LOCAL to this section global
-      // symbol. Here is a workaround for this bug.
-      if (Versym && VersymIndex == VER_NDX_LOCAL && Name == "_gp_disp")
-        continue;
-    }
+    // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly
+    // assigns VER_NDX_LOCAL to this section global symbol. Here is a
+    // workaround for this bug.
+    uint32_t Idx = Versyms[I] & ~VERSYM_HIDDEN;
+    if (Config->EMachine == EM_MIPS && Idx == VER_NDX_LOCAL &&
+        Name == "_gp_disp")
+      continue;
 
-    const Elf_Verdef *Ver = nullptr;
-    if (VersymIndex != VER_NDX_GLOBAL) {
-      if (VersymIndex >= Verdefs.size() || VersymIndex == VER_NDX_LOCAL) {
-        error("corrupt input file: version definition index " +
-              Twine(VersymIndex) + " for symbol " + Name +
-              " is out of bounds\n>>> defined in " + toString(this));
-        continue;
-      }
-      Ver = Verdefs[VersymIndex];
-    } else {
-      VersymIndex = 0;
-    }
-
-    // We do not usually care about alignments of data in shared object
-    // files because the loader takes care of it. However, if we promote a
-    // DSO symbol to point to .bss due to copy relocation, we need to keep
-    // the original alignment requirements. We infer it here.
-    uint64_t Alignment = 1;
-    if (Sym.st_value)
-      Alignment = 1ULL << countTrailingZeros((uint64_t)Sym.st_value);
-    if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) {
-      uint64_t SecAlign = Sections[Sym.st_shndx].sh_addralign;
-      Alignment = std::min(Alignment, SecAlign);
-    }
-    if (Alignment > UINT32_MAX)
-      error(toString(this) + ": alignment too large: " + Name);
-
-    if (!Hidden)
-      Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex);
+    uint64_t Alignment = getAlignment(Sections, Sym);
+    if (!(Versyms[I] & VERSYM_HIDDEN))
+      Symtab->addShared(Name, *this, Sym, Alignment, Idx);
 
     // Also add the symbol with the versioned name to handle undefined symbols
     // with explicit versions.
-    if (Ver) {
-      StringRef VerName = this->StringTable.data() + Ver->getAux()->vda_name;
-      Name = Saver.save(Name + "@" + VerName);
-      Symtab->addShared(Name, *this, Sym, Alignment, VersymIndex);
+    if (Idx == VER_NDX_GLOBAL)
+      continue;
+
+    if (Idx >= Verdefs.size() || Idx == VER_NDX_LOCAL) {
+      error("corrupt input file: version definition index " + Twine(Idx) +
+            " for symbol " + Name + " is out of bounds\n>>> defined in " +
+            toString(this));
+      continue;
     }
+
+    StringRef VerName =
+        this->StringTable.data() + Verdefs[Idx]->getAux()->vda_name;
+    Name = Saver.save(Name + "@" + VerName);
+    Symtab->addShared(Name, *this, Sym, Alignment, Idx);
   }
 }
 
@@ -1117,64 +1167,55 @@
 }
 
 template <class ELFT> void LazyObjFile::parse() {
-  for (StringRef Sym : getSymbolNames())
-    Symtab->addLazyObject<ELFT>(Sym, *this);
-}
-
-template <class ELFT> std::vector<StringRef> LazyObjFile::getElfSymbols() {
-  typedef typename ELFT::Shdr Elf_Shdr;
-  typedef typename ELFT::Sym Elf_Sym;
-  typedef typename ELFT::SymRange Elf_Sym_Range;
-
-  ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(this->MB.getBuffer()));
-  ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this);
-  for (const Elf_Shdr &Sec : Sections) {
-    if (Sec.sh_type != SHT_SYMTAB)
-      continue;
-
-    Elf_Sym_Range Syms = CHECK(Obj.symbols(&Sec), this);
-    uint32_t FirstNonLocal = Sec.sh_info;
-    StringRef StringTable =
-        CHECK(Obj.getStringTableForSymtab(Sec, Sections), this);
-    std::vector<StringRef> V;
-
-    for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal))
-      if (Sym.st_shndx != SHN_UNDEF)
-        V.push_back(CHECK(Sym.getName(StringTable), this));
-    return V;
+  // A lazy object file wraps either a bitcode file or an ELF file.
+  if (isBitcode(this->MB)) {
+    std::unique_ptr<lto::InputFile> Obj =
+        CHECK(lto::InputFile::create(this->MB), this);
+    for (const lto::InputFile::Symbol &Sym : Obj->symbols())
+      if (!Sym.isUndefined())
+        Symtab->addLazyObject<ELFT>(Saver.save(Sym.getName()), *this);
+    return;
   }
-  return {};
-}
-
-std::vector<StringRef> LazyObjFile::getBitcodeSymbols() {
-  std::unique_ptr<lto::InputFile> Obj =
-      CHECK(lto::InputFile::create(this->MB), this);
-  std::vector<StringRef> V;
-  for (const lto::InputFile::Symbol &Sym : Obj->symbols())
-    if (!Sym.isUndefined())
-      V.push_back(Saver.save(Sym.getName()));
-  return V;
-}
-
-// Returns a vector of globally-visible defined symbol names.
-std::vector<StringRef> LazyObjFile::getSymbolNames() {
-  if (isBitcode(this->MB))
-    return getBitcodeSymbols();
 
   switch (getELFKind(this->MB)) {
   case ELF32LEKind:
-    return getElfSymbols<ELF32LE>();
+    addElfSymbols<ELF32LE>();
+    return;
   case ELF32BEKind:
-    return getElfSymbols<ELF32BE>();
+    addElfSymbols<ELF32BE>();
+    return;
   case ELF64LEKind:
-    return getElfSymbols<ELF64LE>();
+    addElfSymbols<ELF64LE>();
+    return;
   case ELF64BEKind:
-    return getElfSymbols<ELF64BE>();
+    addElfSymbols<ELF64BE>();
+    return;
   default:
     llvm_unreachable("getELFKind");
   }
 }
 
+template <class ELFT> void LazyObjFile::addElfSymbols() {
+  ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(MB.getBuffer()));
+  ArrayRef<typename ELFT::Shdr> Sections = CHECK(Obj.sections(), this);
+
+  for (const typename ELFT::Shdr &Sec : Sections) {
+    if (Sec.sh_type != SHT_SYMTAB)
+      continue;
+
+    typename ELFT::SymRange Syms = CHECK(Obj.symbols(&Sec), this);
+    uint32_t FirstGlobal = Sec.sh_info;
+    StringRef StringTable =
+        CHECK(Obj.getStringTableForSymtab(Sec, Sections), this);
+
+    for (const typename ELFT::Sym &Sym : Syms.slice(FirstGlobal))
+      if (Sym.st_shndx != SHN_UNDEF)
+        Symtab->addLazyObject<ELFT>(CHECK(Sym.getName(StringTable), this),
+                                    *this);
+    return;
+  }
+}
+
 template void ArchiveFile::parse<ELF32LE>();
 template void ArchiveFile::parse<ELF32BE>();
 template void ArchiveFile::parse<ELF64LE>();
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 5b9e9d7..8ec5953 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/IR/Comdat.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ELF.h"
@@ -25,7 +26,6 @@
 #include <map>
 
 namespace llvm {
-class DWARFDebugLine;
 class TarWriter;
 struct DILineInfo;
 namespace lto {
@@ -110,6 +110,9 @@
   std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,
                         uint64_t Offset);
 
+  // True if this is an argument for --just-symbols. Usually false.
+  bool JustSymbols = false;
+
 protected:
   InputFile(Kind K, MemoryBufferRef M);
   std::vector<InputSectionBase *> Sections;
@@ -142,7 +145,7 @@
 
 protected:
   ArrayRef<Elf_Sym> ELFSyms;
-  uint32_t FirstNonLocal = 0;
+  uint32_t FirstGlobal = 0;
   ArrayRef<Elf_Word> SymtabSHNDX;
   StringRef StringTable;
   void initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab);
@@ -165,6 +168,7 @@
   static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; }
 
   ArrayRef<Symbol *> getLocalSymbols();
+  ArrayRef<Symbol *> getGlobalSymbols();
 
   ObjFile(MemoryBufferRef M, StringRef ArchiveName);
   void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
@@ -200,6 +204,7 @@
   void
   initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
   void initializeSymbols();
+  void initializeJustSymbols();
   void initializeDwarf();
   InputSectionBase *getRelocTarget(const Elf_Shdr &Sec);
   InputSectionBase *createInputSection(const Elf_Shdr &Sec);
@@ -215,8 +220,15 @@
   // reporting. Linker may find reasonable number of errors in a
   // single object file, so we cache debugging information in order to
   // parse it only once for each object file we link.
+  std::unique_ptr<llvm::DWARFContext> Dwarf;
+  std::vector<const llvm::DWARFDebugLine::LineTable *> LineTables;
   std::unique_ptr<llvm::DWARFDebugLine> DwarfLine;
-  llvm::DenseMap<StringRef, std::pair<unsigned, unsigned>> VariableLoc;
+  struct VarLoc {
+    const llvm::DWARFDebugLine::LineTable *LT;
+    unsigned File;
+    unsigned Line;
+  };
+  llvm::DenseMap<StringRef, VarLoc> VariableLoc;
   llvm::once_flag InitDwarfLine;
 };
 
@@ -242,9 +254,7 @@
   InputFile *fetch();
 
 private:
-  std::vector<StringRef> getSymbolNames();
-  template <class ELFT> std::vector<StringRef> getElfSymbols();
-  std::vector<StringRef> getBitcodeSymbols();
+  template <class ELFT> void addElfSymbols();
 
   bool Seen = false;
   uint64_t OffsetInArchive;
@@ -303,7 +313,9 @@
 
   void parseSoName();
   void parseRest();
-  std::vector<const Elf_Verdef *> parseVerdefs(const Elf_Versym *&Versym);
+  uint32_t getAlignment(ArrayRef<Elf_Shdr> Sections, const Elf_Sym &Sym);
+  std::vector<const Elf_Verdef *> parseVerdefs();
+  std::vector<uint32_t> parseVersyms();
 
   struct NeededVer {
     // The string table offset of the version name in the output file.
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index f7a757e..49426e8 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -142,9 +142,9 @@
     return Offset == uint64_t(-1) ? OS->Size : Offset;
   }
   case Regular:
-    return cast<InputSection>(this)->OutSecOff + Offset;
+    return cast<InputSection>(this->Repl)->OutSecOff + Offset;
   case Synthetic: {
-    auto *IS = cast<InputSection>(this);
+    auto *IS = cast<InputSection>(this->Repl);
     // For synthetic sections we treat offset -1 as the end of the section.
     return IS->OutSecOff + (Offset == uint64_t(-1) ? IS->getSize() : Offset);
   }
@@ -156,23 +156,28 @@
   case Merge:
     const MergeInputSection *MS = cast<MergeInputSection>(this);
     if (InputSection *IS = MS->getParent())
-      return IS->OutSecOff + MS->getOffset(Offset);
+      return cast<InputSection>(IS->Repl)->OutSecOff + MS->getOffset(Offset);
     return MS->getOffset(Offset);
   }
   llvm_unreachable("invalid section kind");
 }
 
+uint64_t SectionBase::getVA(uint64_t Offset) const {
+  const OutputSection *Out = getOutputSection();
+  return (Out ? Out->Addr : 0) + getOffset(Offset);
+}
+
 OutputSection *SectionBase::getOutputSection() {
   InputSection *Sec;
   if (auto *IS = dyn_cast<InputSection>(this))
-    return IS->getParent();
+    Sec = IS;
   else if (auto *MS = dyn_cast<MergeInputSection>(this))
     Sec = MS->getParent();
   else if (auto *EH = dyn_cast<EhInputSection>(this))
     Sec = EH->getParent();
   else
     return cast<OutputSection>(this);
-  return Sec ? Sec->getParent() : nullptr;
+  return Sec ? cast<InputSection>(Sec->Repl)->getParent() : nullptr;
 }
 
 // Decompress section contents if required. Note that this function
@@ -206,15 +211,9 @@
 }
 
 InputSection *InputSectionBase::getLinkOrderDep() const {
-  if ((Flags & SHF_LINK_ORDER) && Link != 0) {
-    InputSectionBase *L = File->getSections()[Link];
-    if (auto *IS = dyn_cast<InputSection>(L))
-      return IS;
-    error("a section with SHF_LINK_ORDER should not refer a non-regular "
-          "section: " +
-          toString(L));
-  }
-  return nullptr;
+  assert(Link);
+  assert(Flags & SHF_LINK_ORDER);
+  return cast<InputSection>(File->getSections()[Link]);
 }
 
 // Returns a source location string. Used to construct an error message.
@@ -331,7 +330,8 @@
 }
 
 InputSectionBase *InputSection::getRelocatedSection() {
-  assert(Type == SHT_RELA || Type == SHT_REL);
+  if (!File || (Type != SHT_RELA && Type != SHT_REL))
+    return nullptr;
   ArrayRef<InputSectionBase *> Sections = File->getSections();
   return Sections[Info];
 }
@@ -355,7 +355,7 @@
 
     // Output section VA is zero for -r, so r_offset is an offset within the
     // section, but for --emit-relocs it is an virtual address.
-    P->r_offset = Sec->getOutputSection()->Addr + Sec->getOffset(Rel.r_offset);
+    P->r_offset = Sec->getVA(Rel.r_offset);
     P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Sym), Type,
                         Config->IsMips64EL);
 
@@ -710,11 +710,10 @@
   const unsigned Bits = Config->Wordsize * 8;
 
   for (const Relocation &Rel : Relocations) {
-    uint64_t Offset = getOffset(Rel.Offset);
-    uint8_t *BufLoc = Buf + Offset;
+    uint8_t *BufLoc = Buf + getOffset(Rel.Offset);
     RelType Type = Rel.Type;
 
-    uint64_t AddrLoc = getOutputSection()->Addr + Offset;
+    uint64_t AddrLoc = getVA(Rel.Offset);
     RelExpr Expr = Rel.Expr;
     uint64_t TargetVA = SignExtend64(
         getRelocTargetVA(Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr), Bits);
@@ -922,16 +921,10 @@
     splitNonStrings(Data, Entsize);
 
   if (Config->GcSections && (Flags & SHF_ALLOC))
-    for (uint64_t Off : LiveOffsets)
+    for (uint32_t Off : LiveOffsets)
       getSectionPiece(Off)->Live = true;
 }
 
-// Do binary search to get a section piece at a given input offset.
-SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) {
-  auto *This = static_cast<const MergeInputSection *>(this);
-  return const_cast<SectionPiece *>(This->getSectionPiece(Offset));
-}
-
 template <class It, class T, class Compare>
 static It fastUpperBound(It First, It Last, const T &Value, Compare Comp) {
   size_t Size = std::distance(First, Last);
@@ -945,7 +938,8 @@
   return Comp(Value, *First) ? First : First + 1;
 }
 
-const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const {
+// Do binary search to get a section piece at a given input offset.
+SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) {
   if (Data.size() <= Offset)
     fatal(toString(this) + ": entry is past the end of the section");
 
@@ -964,13 +958,6 @@
   if (!Live)
     return 0;
 
-  // Initialize OffsetMap lazily.
-  llvm::call_once(InitOffsetMap, [&] {
-    OffsetMap.reserve(Pieces.size());
-    for (size_t I = 0; I < Pieces.size(); ++I)
-      OffsetMap[Pieces[I].InputOff] = I;
-  });
-
   // Find a string starting at a given offset.
   auto It = OffsetMap.find(Offset);
   if (It != OffsetMap.end())
@@ -986,6 +973,12 @@
   return Piece.OutputOff + Addend;
 }
 
+void MergeInputSection::initOffsetMap() {
+  OffsetMap.reserve(Pieces.size());
+  for (size_t I = 0; I < Pieces.size(); ++I)
+    OffsetMap[Pieces[I].InputOff] = I;
+}
+
 template InputSection::InputSection(ObjFile<ELF32LE> &, const ELF32LE::Shdr &,
                                     StringRef);
 template InputSection::InputSection(ObjFile<ELF32BE> &, const ELF32BE::Shdr &,
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index 58549c3..56b5412 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -18,8 +18,6 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Object/ELF.h"
-#include "llvm/Support/Threading.h"
-#include <mutex>
 
 namespace lld {
 namespace elf {
@@ -80,6 +78,8 @@
   // section.
   uint64_t getOffset(uint64_t Offset) const;
 
+  uint64_t getVA(uint64_t Offset) const;
+
 protected:
   SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags,
               uint64_t Entsize, uint64_t Alignment, uint32_t Type,
@@ -249,18 +249,20 @@
 
   // Returns the SectionPiece at a given input section offset.
   SectionPiece *getSectionPiece(uint64_t Offset);
-  const SectionPiece *getSectionPiece(uint64_t Offset) const;
+  const SectionPiece *getSectionPiece(uint64_t Offset) const {
+    return const_cast<MergeInputSection *>(this)->getSectionPiece(Offset);
+  }
 
   SyntheticSection *getParent() const;
+  void initOffsetMap();
 
 private:
   void splitStrings(ArrayRef<uint8_t> A, size_t Size);
   void splitNonStrings(ArrayRef<uint8_t> A, size_t Size);
 
-  mutable llvm::DenseMap<uint32_t, uint32_t> OffsetMap;
-  mutable llvm::once_flag InitOffsetMap;
+  llvm::DenseMap<uint32_t, uint32_t> OffsetMap;
 
-  llvm::DenseSet<uint64_t> LiveOffsets;
+  llvm::DenseSet<uint32_t> LiveOffsets;
 };
 
 struct EhSectionPiece {
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index bdc8a59..d3a3d29 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -112,14 +112,18 @@
           "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes");
 }
 
-void LinkerScript::expandOutputSection(uint64_t Size) {
-  Ctx->OutSec->Size += Size;
+void LinkerScript::expandMemoryRegions(uint64_t Size) {
   if (Ctx->MemRegion)
     expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name,
                        Ctx->OutSec->Name);
-  // FIXME: check LMA region overflow too.
   if (Ctx->LMARegion)
-    Ctx->LMARegion->CurPos += Size;
+    expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name,
+                       Ctx->OutSec->Name);
+}
+
+void LinkerScript::expandOutputSection(uint64_t Size) {
+  Ctx->OutSec->Size += Size;
+  expandMemoryRegions(Size);
 }
 
 void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {
@@ -203,6 +207,34 @@
   Cmd->Provide = false;
 }
 
+// This method is used to handle INSERT AFTER statement. Here we rebuild
+// the list of script commands to mix sections inserted into.
+void LinkerScript::processInsertCommands() {
+  std::vector<BaseCommand *> V;
+  auto Insert = [&](std::vector<BaseCommand *> &From) {
+    V.insert(V.end(), From.begin(), From.end());
+    From.clear();
+  };
+
+  for (BaseCommand *Base : SectionCommands) {
+    if (auto *OS = dyn_cast<OutputSection>(Base)) {
+      Insert(InsertBeforeCommands[OS->Name]);
+      V.push_back(Base);
+      Insert(InsertAfterCommands[OS->Name]);
+      continue;
+    }
+    V.push_back(Base);
+  }
+
+  for (auto &Cmds : {InsertBeforeCommands, InsertAfterCommands})
+    for (const std::pair<StringRef, std::vector<BaseCommand *>> &P : Cmds)
+      if (!P.second.empty())
+        error("unable to INSERT AFTER/BEFORE " + P.first +
+              ": section not defined");
+
+  SectionCommands = std::move(V);
+}
+
 // Symbols defined in script should not be inlined by LTO. At the same time
 // we don't know their final values until late stages of link. Here we scan
 // over symbol assignment commands and create placeholder symbols if needed.
@@ -352,8 +384,11 @@
       // For -emit-relocs we have to ignore entries like
       //   .rela.dyn : { *(.rela.data) }
       // which are common because they are in the default bfd script.
-      if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
-        continue;
+      // We do not ignore SHT_REL[A] linker-synthesized sections here because
+      // want to support scripts that do custom layout for them.
+      if (auto *IS = dyn_cast<InputSection>(Sec))
+        if (IS->getRelocatedSection())
+          continue;
 
       std::string Filename = getFilename(Sec->File);
       if (!Cmd->FilePat.match(Filename) ||
@@ -377,9 +412,17 @@
 void LinkerScript::discard(ArrayRef<InputSection *> V) {
   for (InputSection *S : V) {
     if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab ||
-        S == InX::DynStrTab)
+        S == InX::DynStrTab || S == InX::RelaPlt || S == InX::RelaDyn)
       error("discarding " + S->Name + " section is not allowed");
 
+    // You can discard .hash and .gnu.hash sections by linker scripts. Since
+    // they are synthesized sections, we need to handle them differently than
+    // other regular sections.
+    if (S == InX::GnuHashTab)
+      InX::GnuHashTab = nullptr;
+    if (S == InX::HashTab)
+      InX::HashTab = nullptr;
+
     S->Assigned = false;
     S->Live = false;
     discard(S->DependentSections);
@@ -593,11 +636,11 @@
 void LinkerScript::addOrphanSections() {
   unsigned End = SectionCommands.size();
   StringMap<OutputSection *> Map;
-
   std::vector<OutputSection *> V;
-  for (InputSectionBase *S : InputSections) {
+
+  auto Add = [&](InputSectionBase *S) {
     if (!S->Live || S->Parent)
-      continue;
+      return;
 
     StringRef Name = getOutputSectionName(S);
 
@@ -609,12 +652,24 @@
     if (OutputSection *Sec =
             findByName(makeArrayRef(SectionCommands).slice(0, End), Name)) {
       Sec->addSection(cast<InputSection>(S));
-      continue;
+      return;
     }
 
     if (OutputSection *OS = addInputSec(Map, S, Name))
       V.push_back(OS);
-    assert(S->getOutputSection()->SectionIndex == INT_MAX);
+    assert(S->getOutputSection()->SectionIndex == UINT32_MAX);
+  };
+
+  // For futher --emit-reloc handling code we need target output section
+  // to be created before we create relocation output section, so we want
+  // to create target sections first. We do not want priority handling
+  // for synthetic sections because them are special.
+  for (InputSectionBase *IS : InputSections) {
+    if (auto *Sec = dyn_cast<InputSection>(IS))
+      if (InputSectionBase *Rel = Sec->getRelocatedSection())
+        if (auto *RelIS = dyn_cast_or_null<InputSectionBase>(Rel->Parent))
+          Add(RelIS);
+    Add(IS);
   }
 
   // If no SECTIONS command was given, we should insert sections commands
@@ -655,9 +710,11 @@
 void LinkerScript::switchTo(OutputSection *Sec) {
   if (Ctx->OutSec == Sec)
     return;
-
   Ctx->OutSec = Sec;
+
+  uint64_t Before = advance(0, 1);
   Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment);
+  expandMemoryRegions(Ctx->OutSec->Addr - Before);
 }
 
 // This function searches for a memory region to place the given output
@@ -731,7 +788,9 @@
   for (BaseCommand *Base : Sec->SectionCommands) {
     // This handles the assignments to symbol or to the dot.
     if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
+      Cmd->Offset = Dot - Ctx->OutSec->Addr;
       assignSymbol(Cmd, true);
+      Cmd->Size = Dot - Ctx->OutSec->Addr - Cmd->Offset;
       continue;
     }
 
@@ -785,7 +844,7 @@
   for (BaseCommand *Base : Sec.SectionCommands)
     if (!isa<InputSectionDescription>(*Base))
       return false;
-  return getInputSections(&Sec).empty();
+  return true;
 }
 
 void LinkerScript::adjustSectionsBeforeSorting() {
@@ -817,14 +876,18 @@
       continue;
 
     // A live output section means that some input section was added to it. It
-    // might have been removed (gc, or empty synthetic section), but we at least
-    // know the flags.
+    // might have been removed (if it was empty synthetic section), but we at
+    // least know the flags.
     if (Sec->Live)
-      Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);
-    else
-      Sec->Flags = Flags;
+      Flags = Sec->Flags;
 
-    if (isDiscardable(*Sec)) {
+    // We do not want to keep any special flags for output section
+    // in case it is empty.
+    bool IsEmpty = getInputSections(Sec).empty();
+    if (IsEmpty)
+      Sec->Flags = Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);
+
+    if (IsEmpty && isDiscardable(*Sec)) {
       Sec->Live = false;
       Cmd = nullptr;
     }
diff --git a/ELF/LinkerScript.h b/ELF/LinkerScript.h
index 4eddafa..f808849 100644
--- a/ELF/LinkerScript.h
+++ b/ELF/LinkerScript.h
@@ -86,8 +86,10 @@
 
 // This represents ". = <expr>" or "<symbol> = <expr>".
 struct SymbolAssignment : BaseCommand {
-  SymbolAssignment(StringRef Name, Expr E, std::string Loc)
-      : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {}
+  SymbolAssignment(StringRef Name, Expr E, std::string Loc,
+                   std::string CommandString)
+      : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc),
+        CommandString(CommandString) {}
 
   static bool classof(const BaseCommand *C) {
     return C->Kind == AssignmentKind;
@@ -106,6 +108,16 @@
 
   // Holds file name and line number for error reporting.
   std::string Location;
+
+  // A string representation of this command. We use this for -Map.
+  std::string CommandString;
+
+  // This is just an offset of this assignment command in the output section.
+  unsigned Offset;
+
+  // Size of this assignment command. This is usually 0, but if you move '.'
+  // or use a BYTE()-family command, this may be greater than 0."
+  unsigned Size;
 };
 
 // Linker scripts allow additional constraints to be put on ouput sections.
@@ -178,11 +190,15 @@
 
 // Represents BYTE(), SHORT(), LONG(), or QUAD().
 struct ByteCommand : BaseCommand {
-  ByteCommand(Expr E, unsigned Size)
-      : BaseCommand(ByteKind), Expression(E), Size(Size) {}
+  ByteCommand(Expr E, unsigned Size, std::string CommandString)
+      : BaseCommand(ByteKind), CommandString(CommandString), Expression(E),
+        Size(Size) {}
 
   static bool classof(const BaseCommand *C) { return C->Kind == ByteKind; }
 
+  // Keeps string representing the command. Used for -Map" is perhaps better.
+  std::string CommandString;
+
   Expr Expression;
   unsigned Offset;
   unsigned Size;
@@ -216,6 +232,7 @@
   void assignSymbol(SymbolAssignment *Cmd, bool InSec);
   void setDot(Expr E, const Twine &Loc, bool InSec);
   void expandOutputSection(uint64_t Size);
+  void expandMemoryRegions(uint64_t Size);
 
   std::vector<InputSection *>
   computeInputSections(const InputSectionDescription *);
@@ -267,6 +284,9 @@
   void processSectionCommands();
   void declareSymbols();
 
+  // Used to handle INSERT AFTER statements.
+  void processInsertCommands();
+
   // SECTIONS command list.
   std::vector<BaseCommand *> SectionCommands;
 
@@ -285,6 +305,11 @@
 
   // A list of symbols referenced by the script.
   std::vector<llvm::StringRef> ReferencedSymbols;
+
+  // Used to implement INSERT [AFTER|BEFORE]. Contains commands that need
+  // to be inserted into SECTIONS commands list.
+  llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;
+  llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertBeforeCommands;
 };
 
 extern LinkerScript *Script;
diff --git a/ELF/MapFile.cpp b/ELF/MapFile.cpp
index ae13f13..f5dcec8 100644
--- a/ELF/MapFile.cpp
+++ b/ELF/MapFile.cpp
@@ -28,6 +28,8 @@
 #include "SyntheticSections.h"
 #include "lld/Common/Strings.h"
 #include "lld/Common/Threads.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
@@ -38,6 +40,9 @@
 
 typedef DenseMap<const SectionBase *, SmallVector<Symbol *, 4>> SymbolMapTy;
 
+static const std::string Indent8 = "        ";          // 8 spaces
+static const std::string Indent16 = "                "; // 16 spaces
+
 // Print out the first three columns of a line.
 static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size,
                         uint64_t Align) {
@@ -45,8 +50,6 @@
   OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align);
 }
 
-static std::string indent(int Depth) { return std::string(Depth * 8, ' '); }
-
 // Returns a list of all symbols that we want to print out.
 static std::vector<Symbol *> getSymbols() {
   std::vector<Symbol *> V;
@@ -100,7 +103,7 @@
   parallelForEachN(0, Syms.size(), [&](size_t I) {
     raw_string_ostream OS(Str[I]);
     writeHeader(OS, Syms[I]->getVA(), Syms[I]->getSize(), 0);
-    OS << indent(2) << toString(*Syms[I]);
+    OS << Indent16 << toString(*Syms[I]);
   });
 
   DenseMap<Symbol *, std::string> Ret;
@@ -109,6 +112,43 @@
   return Ret;
 }
 
+// Print .eh_frame contents. Since the section consists of EhSectionPieces,
+// we need a specialized printer for that section.
+//
+// .eh_frame tend to contain a lot of section pieces that are contiguous
+// both in input file and output file. Such pieces are squashed before
+// being displayed to make output compact.
+static void printEhFrame(raw_ostream &OS, OutputSection *OSec) {
+  std::vector<EhSectionPiece> Pieces;
+
+  auto Add = [&](const EhSectionPiece &P) {
+    // If P is adjacent to Last, squash the two.
+    if (!Pieces.empty()) {
+      EhSectionPiece &Last = Pieces.back();
+      if (Last.Sec == P.Sec && Last.InputOff + Last.Size == P.InputOff &&
+          Last.OutputOff + Last.Size == P.OutputOff) {
+        Last.Size += P.Size;
+        return;
+      }
+    }
+    Pieces.push_back(P);
+  };
+
+  // Gather section pieces.
+  for (const CieRecord *Rec : InX::EhFrame->getCieRecords()) {
+    Add(*Rec->Cie);
+    for (const EhSectionPiece *Fde : Rec->Fdes)
+      Add(*Fde);
+  }
+
+  // Print out section pieces.
+  for (EhSectionPiece &P : Pieces) {
+    writeHeader(OS, OSec->Addr + P.OutputOff, P.Size, 0);
+    OS << Indent8 << toString(P.Sec->File) << ":(" << P.Sec->Name << "+0x"
+       << Twine::utohexstr(P.InputOff) + ")\n";
+  }
+}
+
 void elf::writeMapFile() {
   if (Config->MapFile.empty())
     return;
@@ -137,11 +177,80 @@
     OS << OSec->Name << '\n';
 
     // Dump symbols for each input section.
-    for (InputSection *IS : getInputSections(OSec)) {
-      writeHeader(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), IS->Alignment);
-      OS << indent(1) << toString(IS) << '\n';
-      for (Symbol *Sym : SectionSyms[IS])
-        OS << SymStr[Sym] << '\n';
+    for (BaseCommand *Base : OSec->SectionCommands) {
+      if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) {
+        for (InputSection *IS : ISD->Sections) {
+          if (IS == InX::EhFrame) {
+            printEhFrame(OS, OSec);
+            continue;
+          }
+
+          writeHeader(OS, IS->getVA(0), IS->getSize(), IS->Alignment);
+          OS << Indent8 << toString(IS) << '\n';
+          for (Symbol *Sym : SectionSyms[IS])
+            OS << SymStr[Sym] << '\n';
+        }
+        continue;
+      }
+
+      if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {
+        writeHeader(OS, OSec->Addr + Cmd->Offset, Cmd->Size, 1);
+        OS << Indent8 << Cmd->CommandString << '\n';
+        continue;
+      }
+
+      if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
+        writeHeader(OS, OSec->Addr + Cmd->Offset, Cmd->Size, 1);
+        OS << Indent8 << Cmd->CommandString << '\n';
+        continue;
+      }
     }
   }
 }
+
+static void print(StringRef A, StringRef B) {
+  outs() << left_justify(A, 49) << " " << B << "\n";
+}
+
+// Output a cross reference table to stdout. This is for --cref.
+//
+// For each global symbol, we print out a file that defines the symbol
+// followed by files that uses that symbol. Here is an example.
+//
+//     strlen     /lib/x86_64-linux-gnu/libc.so.6
+//                tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o
+//                lib/libLLVMSupport.a(PrettyStackTrace.cpp.o)
+//
+// In this case, strlen is defined by libc.so.6 and used by other two
+// files.
+void elf::writeCrossReferenceTable() {
+  if (!Config->Cref)
+    return;
+
+  // Collect symbols and files.
+  MapVector<Symbol *, SetVector<InputFile *>> Map;
+  for (InputFile *File : ObjectFiles) {
+    for (Symbol *Sym : File->getSymbols()) {
+      if (isa<SharedSymbol>(Sym))
+        Map[Sym].insert(File);
+      if (auto *D = dyn_cast<Defined>(Sym))
+        if (!D->isLocal() && (!D->Section || D->Section->Live))
+          Map[D].insert(File);
+    }
+  }
+
+  // Print out a header.
+  outs() << "Cross Reference Table\n\n";
+  print("Symbol", "File");
+
+  // Print out a table.
+  for (auto KV : Map) {
+    Symbol *Sym = KV.first;
+    SetVector<InputFile *> &Files = KV.second;
+
+    print(toString(*Sym), toString(Sym->File));
+    for (InputFile *File : Files)
+      if (File != Sym->File)
+        print("", toString(File));
+  }
+}
diff --git a/ELF/MapFile.h b/ELF/MapFile.h
index 2d93e26..0282425 100644
--- a/ELF/MapFile.h
+++ b/ELF/MapFile.h
@@ -13,6 +13,7 @@
 namespace lld {
 namespace elf {
 void writeMapFile();
+void writeCrossReferenceTable();
 } // namespace elf
 } // namespace lld
 
diff --git a/ELF/Options.td b/ELF/Options.td
index b1c7a1d..82a2a1c 100644
--- a/ELF/Options.td
+++ b/ELF/Options.td
@@ -75,6 +75,10 @@
 def color_diagnostics_eq: J<"color-diagnostics=">,
   HelpText<"Use colors in diagnostics">;
 
+defm cref: B<"cref",
+    "Output cross reference table",
+    "Do not output cross reference table">;
+
 defm define_common: B<"define-common",
     "Assign space to common symbols",
     "Do not assign space to common symbols">;
@@ -180,6 +184,8 @@
 defm init: Eq<"init">, HelpText<"Specify an initializer function">,
   MetaVarName<"<symbol>">;
 
+defm just_symbols: Eq<"just-symbols">, HelpText<"Just link symbols">;
+
 defm library: Eq<"library">, HelpText<"Root name of library to use">,
   MetaVarName<"<libName>">;
 
@@ -418,7 +424,6 @@
 
 // Options listed below are silently ignored for now for compatibility.
 def allow_shlib_undefined: F<"allow-shlib-undefined">;
-def cref: F<"cref">;
 def detect_odr_violations: F<"detect-odr-violations">;
 def g: Flag<["-"], "g">;
 def long_plt: F<"long-plt">;
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 9d5ebe5..8e9e757 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -25,7 +25,6 @@
 using namespace llvm;
 using namespace llvm::dwarf;
 using namespace llvm::object;
-using namespace llvm::support::endian;
 using namespace llvm::ELF;
 
 using namespace lld;
@@ -72,9 +71,7 @@
 OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
     : BaseCommand(OutputSectionKind),
       SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
-                  /*Info*/ 0,
-                  /*Link*/ 0),
-      SectionIndex(INT_MAX) {
+                  /*Info*/ 0, /*Link*/ 0) {
   Live = false;
 }
 
@@ -100,7 +97,8 @@
     Flags = IS->Flags;
   } else {
     // Otherwise, check if new type or flags are compatible with existing ones.
-    if ((Flags & (SHF_ALLOC | SHF_TLS)) != (IS->Flags & (SHF_ALLOC | SHF_TLS)))
+    unsigned Mask = SHF_ALLOC | SHF_TLS | SHF_LINK_ORDER;
+    if ((Flags & Mask) != (IS->Flags & Mask))
       error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
             ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
             ": 0x" + utohexstr(Flags));
@@ -214,11 +212,11 @@
   if (Size == 1)
     *Buf = Data;
   else if (Size == 2)
-    write16(Buf, Data, Config->Endianness);
+    write16(Buf, Data);
   else if (Size == 4)
-    write32(Buf, Data, Config->Endianness);
+    write32(Buf, Data);
   else if (Size == 8)
-    write64(Buf, Data, Config->Endianness);
+    write64(Buf, Data);
   else
     llvm_unreachable("unsupported Size argument");
 }
@@ -367,8 +365,6 @@
   assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
   X = X.substr(6);
   Y = Y.substr(6);
-  if (X.empty() && Y.empty())
-    return false;
   return X < Y;
 }
 
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index ce6bff3..514b9da 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -51,7 +51,7 @@
   uint64_t getLMA() const { return PtLoad ? Addr + PtLoad->LMAOffset : Addr; }
   template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
 
-  unsigned SectionIndex;
+  uint32_t SectionIndex = UINT32_MAX;
   unsigned SortRank;
 
   uint32_t getPhdrFlags() const;
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index bf67e61..bc4f4b2 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -814,7 +814,8 @@
     error(
         "can't create dynamic relocation " + toString(Type) + " against " +
         (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) +
-        " in readonly segment; recompile object files with -fPIC" +
+        " in readonly segment; recompile object files with -fPIC "
+        "or pass '-Wl,-z,notext' to allow text relocations in the output" +
         getLocation(Sec, Sym, Offset));
     return Expr;
   }
@@ -875,6 +876,17 @@
     // that points to the real function is a dedicated got entry used by the
     // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
     // R_386_JMP_SLOT, etc).
+
+    // For position independent executable on i386, the plt entry requires ebx
+    // to be set. This causes two problems:
+    // * If some code has a direct reference to a function, it was probably
+    //   compiled without -fPIE/-fPIC and doesn't maintain ebx.
+    // * If a library definition gets preempted to the executable, it will have
+    //   the wrong ebx value.
+    if (Config->Pie && Config->EMachine == EM_386)
+      errorOrWarn("symbol '" + toString(Sym) +
+                  "' cannot be preempted; recompile with -fPIE" +
+                  getLocation(Sec, Sym, Offset));
     Sym.NeedsPltAddr = true;
     Expr = toPlt(Expr);
     Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
@@ -1206,17 +1218,30 @@
 //
 // We follow a simple but conservative heuristic to place ThunkSections at
 // offsets that are multiples of a Target specific branch range.
-// For an InputSectionRange that is smaller than the range, a single
+// For an InputSectionDescription that is smaller than the range, a single
 // ThunkSection at the end of the range will do.
+//
+// For an InputSectionDescription that is more than twice the size of the range,
+// we place the last ThunkSection at range bytes from the end of the
+// InputSectionDescription in order to increase the likelihood that the
+// distance from a thunk to its target will be sufficiently small to
+// allow for the creation of a short thunk.
 void ThunkCreator::createInitialThunkSections(
     ArrayRef<OutputSection *> OutputSections) {
   forEachInputSectionDescription(
       OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {
         if (ISD->Sections.empty())
           return;
+        uint32_t ISDBegin = ISD->Sections.front()->OutSecOff;
+        uint32_t ISDEnd =
+            ISD->Sections.back()->OutSecOff + ISD->Sections.back()->getSize();
+        uint32_t LastThunkLowerBound = -1;
+        if (ISDEnd - ISDBegin > Target->ThunkSectionSpacing * 2)
+          LastThunkLowerBound = ISDEnd - Target->ThunkSectionSpacing;
+
         uint32_t ISLimit;
-        uint32_t PrevISLimit = ISD->Sections.front()->OutSecOff;
-        uint32_t ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing;
+        uint32_t PrevISLimit = ISDBegin;
+        uint32_t ThunkUpperBound = ISDBegin + Target->ThunkSectionSpacing;
 
         for (const InputSection *IS : ISD->Sections) {
           ISLimit = IS->OutSecOff + IS->getSize();
@@ -1224,6 +1249,8 @@
             addThunkSection(OS, ISD, PrevISLimit);
             ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing;
           }
+          if (ISLimit > LastThunkLowerBound)
+            break;
           PrevISLimit = ISLimit;
         }
         addThunkSection(OS, ISD, ISLimit);
@@ -1240,17 +1267,22 @@
 
 std::pair<Thunk *, bool> ThunkCreator::getThunk(Symbol &Sym, RelType Type,
                                                 uint64_t Src) {
-  auto Res = ThunkedSymbols.insert({&Sym, std::vector<Thunk *>()});
-  if (!Res.second) {
-    // Check existing Thunks for Sym to see if they can be reused
-    for (Thunk *ET : Res.first->second)
-      if (ET->isCompatibleWith(Type) &&
-          Target->inBranchRange(Type, Src, ET->ThunkSym->getVA()))
-        return std::make_pair(ET, false);
-  }
+  std::vector<Thunk *> *ThunkVec = nullptr;
+  // We use (section, offset) pair to find the thunk position if possible so
+  // that we create only one thunk for aliased symbols or ICFed sections.
+  if (auto *D = dyn_cast<Defined>(&Sym))
+    if (!D->isInPlt() && D->Section)
+      ThunkVec = &ThunkedSymbolsBySection[{D->Section->Repl, D->Value}];
+  if (!ThunkVec)
+    ThunkVec = &ThunkedSymbols[&Sym];
+  // Check existing Thunks for Sym to see if they can be reused
+  for (Thunk *ET : *ThunkVec)
+    if (ET->isCompatibleWith(Type) &&
+        Target->inBranchRange(Type, Src, ET->getThunkTargetSym()->getVA()))
+      return std::make_pair(ET, false);
   // No existing compatible Thunk in range, create a new one
   Thunk *T = addThunk(Type, Sym);
-  Res.first->second.push_back(T);
+  ThunkVec->push_back(T);
   return std::make_pair(T, true);
 }
 
@@ -1326,7 +1358,7 @@
       OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {
         for (InputSection *IS : ISD->Sections)
           for (Relocation &Rel : IS->Relocations) {
-            uint64_t Src = OS->Addr + IS->OutSecOff + Rel.Offset;
+            uint64_t Src = IS->getVA(Rel.Offset);
 
             // If we are a relocation to an existing Thunk, check if it is
             // still in range. If not then Rel will be altered to point to its
@@ -1341,7 +1373,6 @@
             bool IsNew;
             std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src);
             if (IsNew) {
-              AddressesChanged = true;
               // Find or create a ThunkSection for the new Thunk
               ThunkSection *TS;
               if (auto *TIS = T->getTargetInputSection())
@@ -1349,13 +1380,18 @@
               else
                 TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src);
               TS->addThunk(T);
-              Thunks[T->ThunkSym] = T;
+              Thunks[T->getThunkTargetSym()] = T;
             }
             // Redirect relocation to Thunk, we never go via the PLT to a Thunk
-            Rel.Sym = T->ThunkSym;
+            Rel.Sym = T->getThunkTargetSym();
             Rel.Expr = fromPlt(Rel.Expr);
           }
+        for (auto &P : ISD->ThunkSections)
+          AddressesChanged |= P.first->assignOffsets();
       });
+  for (auto &P : ThunkedSections)
+    AddressesChanged |= P.second->assignOffsets();
+
   // Merge all created synthetic ThunkSections back into OutputSection
   mergeThunks(OutputSections);
   ++Pass;
diff --git a/ELF/Relocations.h b/ELF/Relocations.h
index 7b142e1..69afe31 100644
--- a/ELF/Relocations.h
+++ b/ELF/Relocations.h
@@ -21,7 +21,7 @@
 class InputSection;
 class InputSectionBase;
 class OutputSection;
-class OutputSection;
+class SectionBase;
 
 // Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL.
 typedef uint32_t RelType;
@@ -161,6 +161,8 @@
   bool normalizeExistingThunk(Relocation &Rel, uint64_t Src);
 
   // Record all the available Thunks for a Symbol
+  llvm::DenseMap<std::pair<SectionBase *, uint64_t>, std::vector<Thunk *>>
+      ThunkedSymbolsBySection;
   llvm::DenseMap<Symbol *, std::vector<Thunk *>> ThunkedSymbols;
 
   // Find a Thunk from the Thunks symbol definition, we can use this to find
diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp
index c68c25a..ff650d8 100644
--- a/ELF/ScriptParser.cpp
+++ b/ELF/ScriptParser.cpp
@@ -267,7 +267,8 @@
   Expr E = readExpr();
   if (!atEOF())
     setError("EOF expected, but got " + next());
-  SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation());
+  SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation(),
+                                                 "" /*CommandString*/);
   Script->SectionCommands.push_back(Cmd);
 }
 
@@ -436,6 +437,7 @@
   Config->SingleRoRx = true;
 
   expect("{");
+  std::vector<BaseCommand *> V;
   while (!errorCount() && !consume("}")) {
     StringRef Tok = next();
     BaseCommand *Cmd = readProvideOrAssignment(Tok);
@@ -445,17 +447,34 @@
       else
         Cmd = readOutputSectionDescription(Tok);
     }
-    Script->SectionCommands.push_back(Cmd);
+    V.push_back(Cmd);
   }
+
+  if (!atEOF() && consume("INSERT")) {
+    std::vector<BaseCommand *> *Dest = nullptr;
+    if (consume("AFTER"))
+      Dest = &Script->InsertAfterCommands[next()];
+    else if (consume("BEFORE"))
+      Dest = &Script->InsertBeforeCommands[next()];
+    else
+      setError("expected AFTER/BEFORE, but got '" + next() + "'");
+    if (Dest)
+      Dest->insert(Dest->end(), V.begin(), V.end());
+    return;
+  }
+
+  Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(),
+                                 V.end());
 }
 
 static int precedence(StringRef Op) {
   return StringSwitch<int>(Op)
-      .Cases("*", "/", "%", 5)
-      .Cases("+", "-", 4)
-      .Cases("<<", ">>", 3)
-      .Cases("<", "<=", ">", ">=", "==", "!=", 2)
-      .Cases("&", "|", 1)
+      .Cases("*", "/", "%", 6)
+      .Cases("+", "-", 5)
+      .Cases("<<", ">>", 4)
+      .Cases("<", "<=", ">", ">=", "==", "!=", 3)
+      .Case("&", 2)
+      .Case("|", 1)
       .Default(-1);
 }
 
@@ -774,6 +793,7 @@
 }
 
 SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
+  size_t OldPos = Pos;
   StringRef Op = next();
   assert(Op == "=" || Op == "+=");
   Expr E = readExpr();
@@ -781,7 +801,11 @@
     std::string Loc = getCurrentLocation();
     E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); };
   }
-  return make<SymbolAssignment>(Name, E, getCurrentLocation());
+
+  std::string CommandString =
+      Name.str() + " " +
+      llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");
+  return make<SymbolAssignment>(Name, E, getCurrentLocation(), CommandString);
 }
 
 // This is an operator-precedence parser to parse a linker
@@ -935,7 +959,13 @@
                  .Default(-1);
   if (Size == -1)
     return nullptr;
-  return make<ByteCommand>(readParenExpr(), Size);
+
+  size_t OldPos = Pos;
+  Expr E = readParenExpr();
+  std::string CommandString =
+      Tok.str() + " " +
+      llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");
+  return make<ByteCommand>(E, Size, CommandString);
 }
 
 StringRef ScriptParser::readParenLiteral() {
@@ -1067,6 +1097,16 @@
       return Cmd->getLMA();
     };
   }
+  if (Tok == "MAX" || Tok == "MIN") {
+    expect("(");
+    Expr A = readExpr();
+    expect(",");
+    Expr B = readExpr();
+    expect(")");
+    if (Tok == "MIN")
+      return [=] { return std::min(A().getValue(), B().getValue()); };
+    return [=] { return std::max(A().getValue(), B().getValue()); };
+  }
   if (Tok == "ORIGIN") {
     StringRef Name = readParenLiteral();
     if (Script->MemoryRegions.count(Name) == 0) {
@@ -1310,11 +1350,10 @@
     uint64_t Length = readMemoryAssignment("LENGTH", "len", "l");
 
     // Add the memory region to the region map.
-    if (Script->MemoryRegions.count(Name))
-      setError("region '" + Name + "' already defined");
     MemoryRegion *MR =
         make<MemoryRegion>(Name, Origin, Length, Flags, NegFlags);
-    Script->MemoryRegions[Name] = MR;
+    if (!Script->MemoryRegions.insert({Name, MR}).second)
+      setError("region '" + Name + "' already defined");
   }
 }
 
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index eaf7005..40c7d7f 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -130,7 +130,10 @@
 
   for (InputFile *File : LTO->compile()) {
     DenseSet<CachedHashStringRef> DummyGroups;
-    cast<ObjFile<ELFT>>(File)->parse(DummyGroups);
+    auto *Obj = cast<ObjFile<ELFT>>(File);
+    Obj->parse(DummyGroups);
+    for (Symbol *Sym : Obj->getGlobalSymbols())
+      Sym->parseSymbolVersion();
     ObjectFiles.push_back(File);
   }
 }
@@ -410,20 +413,17 @@
   return S;
 }
 
-static void warnOrError(const Twine &Msg) {
-  if (Config->AllowMultipleDefinition)
-    warn(Msg);
-  else
-    error(Msg);
-}
-
 static void reportDuplicate(Symbol *Sym, InputFile *NewFile) {
-  warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " +
-              toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
+  if (!Config->AllowMultipleDefinition)
+    error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " +
+          toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
 }
 
 static void reportDuplicate(Symbol *Sym, InputFile *NewFile,
                             InputSectionBase *ErrSec, uint64_t ErrOffset) {
+  if (Config->AllowMultipleDefinition)
+    return;
+
   Defined *D = cast<Defined>(Sym);
   if (!D->Section || !ErrSec) {
     reportDuplicate(Sym, NewFile);
@@ -450,7 +450,7 @@
   if (!Src2.empty())
     Msg += Src2 + "\n>>>            ";
   Msg += Obj2;
-  warnOrError(Msg);
+  error(Msg);
 }
 
 Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 58ed899..8ac3e5f 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -56,7 +56,6 @@
     if (!IS)
       return D.Value;
 
-    IS = IS->Repl;
     uint64_t Offset = D.Value;
 
     // An object in an SHF_MERGE section might be referenced via a
@@ -75,8 +74,6 @@
       Addend = 0;
     }
 
-    const OutputSection *OutSec = IS->getOutputSection();
-
     // In the typical case, this is actually very simple and boils
     // down to adding together 3 numbers:
     // 1. The address of the output section.
@@ -87,7 +84,7 @@
     // If you understand the data structures involved with this next
     // line (and how they get built), then you have a pretty good
     // understanding of the linker.
-    uint64_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset(Offset);
+    uint64_t VA = IS->getVA(Offset);
 
     if (D.isTls() && !Config->Relocatable) {
       if (!Out::TlsPhdr)
@@ -100,7 +97,7 @@
   case Symbol::SharedKind: {
     auto &SS = cast<SharedSymbol>(Sym);
     if (SS.CopyRelSec)
-      return SS.CopyRelSec->getParent()->Addr + SS.CopyRelSec->OutSecOff;
+      return SS.CopyRelSec->getVA(0);
     if (SS.NeedsPltAddr)
       return Sym.getPltVA();
     return 0;
@@ -139,8 +136,7 @@
 uint64_t Symbol::getPltVA() const {
   if (this->IsInIplt)
     return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize;
-  return InX::Plt->getVA() + Target->PltHeaderSize +
-         PltIndex * Target->PltEntrySize;
+  return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex);
 }
 
 uint64_t Symbol::getSize() const {
@@ -154,7 +150,7 @@
 OutputSection *Symbol::getOutputSection() const {
   if (auto *S = dyn_cast<Defined>(this)) {
     if (auto *Sec = S->Section)
-      return Sec->Repl->getOutputSection();
+      return Sec->getOutputSection();
     return nullptr;
   }
 
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index 6057bd8..5c214d0 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -47,16 +47,14 @@
 using namespace llvm::ELF;
 using namespace llvm::object;
 using namespace llvm::support;
-using namespace llvm::support::endian;
 
 using namespace lld;
 using namespace lld::elf;
 
-constexpr size_t MergeNoTailSection::NumShards;
+using llvm::support::endian::write32le;
+using llvm::support::endian::write64le;
 
-static void write32(void *Buf, uint32_t Val) {
-  endian::write32(Buf, Val, Config->Endianness);
-}
+constexpr size_t MergeNoTailSection::NumShards;
 
 uint64_t SyntheticSection::getVA() const {
   if (OutputSection *Sec = getParent())
@@ -67,7 +65,7 @@
 // Returns an LLD version string.
 static ArrayRef<uint8_t> getVersion() {
   // Check LLD_VERSION first for ease of testing.
-  // You can get consitent output by using the environment variable.
+  // You can get consistent output by using the environment variable.
   // This is only for testing.
   StringRef S = getenv("LLD_VERSION");
   if (S.empty())
@@ -266,8 +264,8 @@
   return Sec;
 }
 
-Symbol *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
-                               uint64_t Size, InputSectionBase &Section) {
+Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
+                                uint64_t Size, InputSectionBase &Section) {
   auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type,
                           Value, Size, &Section);
   if (InX::SymTab)
@@ -381,7 +379,7 @@
 template <class ELFT, class RelTy>
 CieRecord *EhFrameSection::addCie(EhSectionPiece &Cie, ArrayRef<RelTy> Rels) {
   auto *Sec = cast<EhInputSection>(Cie.Sec);
-  if (read32(Cie.data().data() + 4, Config->Endianness) != 0)
+  if (read32(Cie.data().data() + 4) != 0)
     fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame");
 
   Symbol *Personality = nullptr;
@@ -440,7 +438,7 @@
       return;
 
     size_t Offset = Piece.InputOff;
-    uint32_t ID = read32(Piece.data().data() + 4, Config->Endianness);
+    uint32_t ID = read32(Piece.data().data() + 4);
     if (ID == 0) {
       OffsetToCie[Offset] = addCie<ELFT>(Piece, Rels);
       continue;
@@ -538,11 +536,11 @@
 static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
   switch (Size) {
   case DW_EH_PE_udata2:
-    return read16(Buf, Config->Endianness);
+    return read16(Buf);
   case DW_EH_PE_udata4:
-    return read32(Buf, Config->Endianness);
+    return read32(Buf);
   case DW_EH_PE_udata8:
-    return read64(Buf, Config->Endianness);
+    return read64(Buf);
   case DW_EH_PE_absptr:
     return readUint(Buf);
   }
@@ -589,7 +587,15 @@
 
 GotSection::GotSection()
     : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
-                       Target->GotEntrySize, ".got") {}
+                       Target->GotEntrySize, ".got") {
+  // PPC64 saves the ElfSym::GlobalOffsetTable .TOC. as the first entry in the
+  // .got. If there are no references to .TOC. in the symbol table,
+  // ElfSym::GlobalOffsetTable will not be defined and we won't need to save
+  // .TOC. in the .got. When it is defined, we increase NumEntries by the number
+  // of entries used to emit ElfSym::GlobalOffsetTable.
+  if (ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt)
+    NumEntries += Target->GotHeaderEntriesNum;
+}
 
 void GotSection::addEntry(Symbol &Sym) {
   Sym.GotIndex = NumEntries;
@@ -623,19 +629,24 @@
   return B.GlobalDynIndex * Config->Wordsize;
 }
 
-void GotSection::finalizeContents() { Size = NumEntries * Config->Wordsize; }
+void GotSection::finalizeContents() {
+  Size = NumEntries * Config->Wordsize;
+}
 
 bool GotSection::empty() const {
   // We need to emit a GOT even if it's empty if there's a relocation that is
   // relative to GOT(such as GOTOFFREL) or there's a symbol that points to a GOT
-  // (i.e. _GLOBAL_OFFSET_TABLE_).
-  return NumEntries == 0 && !HasGotOffRel && !ElfSym::GlobalOffsetTable;
+  // (i.e. _GLOBAL_OFFSET_TABLE_) that the target defines relative to the .got.
+  return NumEntries == 0 && !HasGotOffRel &&
+         !(ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt);
 }
 
 void GotSection::writeTo(uint8_t *Buf) {
   // Buf points to the start of this section's buffer,
   // whereas InputSectionBase::relocateAlloc() expects its argument
   // to point to the start of the output section.
+  Target->writeGotHeader(Buf);
+  Buf += Target->GotHeaderEntriesNum * Target->GotEntrySize;
   relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size);
 }
 
@@ -900,6 +911,14 @@
   }
 }
 
+bool GotPltSection::empty() const {
+  // We need to emit a GOT.PLT even if it's empty if there's a symbol that
+  // references the _GLOBAL_OFFSET_TABLE_ and the Target defines the symbol
+  // relative to the .got.plt section.
+  return Entries.empty() &&
+         !(ElfSym::GlobalOffsetTable && Target->GotBaseSymInGotPlt);
+}
+
 // On ARM the IgotPltSection is part of the GotSection, on other Targets it is
 // part of the .got.plt
 IgotPltSection::IgotPltSection()
@@ -1005,8 +1024,7 @@
 
 template <class ELFT>
 void DynamicSection<ELFT>::addInSec(int32_t Tag, InputSection *Sec) {
-  Entries.push_back(
-      {Tag, [=] { return Sec->getParent()->Addr + Sec->OutSecOff; }});
+  Entries.push_back({Tag, [=] { return Sec->getVA(0); }});
 }
 
 template <class ELFT>
@@ -1183,7 +1201,7 @@
 }
 
 uint64_t DynamicReloc::getOffset() const {
-  return InputSec->getOutputSection()->Addr + InputSec->getOffset(OffsetInSec);
+  return InputSec->getVA(OffsetInSec);
 }
 
 int64_t DynamicReloc::computeAddend() const {
@@ -1722,7 +1740,7 @@
   write32(Buf, NBuckets);
   write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size());
   write32(Buf + 8, MaskWords);
-  write32(Buf + 12, getShift2());
+  write32(Buf + 12, Shift2);
   Buf += 16;
 
   // Write a bloom filter and a hash table.
@@ -1744,7 +1762,7 @@
     size_t I = (Sym.Hash / C) & (MaskWords - 1);
     uint64_t Val = readUint(Buf + I * Config->Wordsize);
     Val |= uint64_t(1) << (Sym.Hash % C);
-    Val |= uint64_t(1) << ((Sym.Hash >> getShift2()) % C);
+    Val |= uint64_t(1) << ((Sym.Hash >> Shift2) % C);
     writeUint(Buf + I * Config->Wordsize, Val);
   }
 }
@@ -1792,15 +1810,21 @@
           return SS->CopyRelSec == nullptr && !SS->NeedsPltAddr;
         return !S.Sym->isDefined();
       });
-  if (Mid == V.end())
-    return;
 
   // We chose load factor 4 for the on-disk hash table. For each hash
   // collision, the dynamic linker will compare a uint32_t hash value.
-  // Since the integer comparison is quite fast, we believe we can make
-  // the load factor even larger. 4 is just a conservative choice.
+  // Since the integer comparison is quite fast, we believe we can
+  // make the load factor even larger. 4 is just a conservative choice.
+  //
+  // Note that we don't want to create a zero-sized hash table because
+  // Android loader as of 2018 doesn't like a .gnu.hash containing such
+  // table. If that's the case, we create a hash table with one unused
+  // dummy slot.
   NBuckets = std::max<size_t>((V.end() - Mid) / 4, 1);
 
+  if (Mid == V.end())
+    return;
+
   for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) {
     Symbol *B = Ent.Sym;
     uint32_t Hash = hashGnu(B->getName());
@@ -2128,8 +2152,7 @@
   // Write the address area.
   for (GdbIndexChunk &D : Chunks) {
     for (GdbIndexChunk::AddressEntry &E : D.AddressAreas) {
-      uint64_t BaseAddr =
-          E.Section->getParent()->Addr + E.Section->getOffset(0);
+      uint64_t BaseAddr = E.Section->getVA(0);
       write64le(Buf, BaseAddr + E.LowAddress);
       write64le(Buf + 8, BaseAddr + E.HighAddress);
       write32le(Buf + 16, E.CuIndex);
@@ -2312,8 +2335,7 @@
 template <class ELFT>
 void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
   SharedFile<ELFT> &File = SS->getFile<ELFT>();
-  const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];
-  if (!Ver) {
+  if (SS->VerdefIndex == VER_NDX_GLOBAL) {
     SS->VersionId = VER_NDX_GLOBAL;
     return;
   }
@@ -2323,7 +2345,9 @@
   // for the soname.
   if (File.VerdefMap.empty())
     Needed.push_back({&File, InX::DynStrTab->addString(File.SoName)});
+  const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];
   typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver];
+
   // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef,
   // prepare to create one by allocating a version identifier and creating a
   // dynstr entry for the version name.
@@ -2549,8 +2573,11 @@
     }
     (*I)->addSection(MS);
   }
-  for (auto *MS : MergeSections)
+  for (auto *MS : MergeSections) {
     MS->finalizeContents();
+    parallelForEach(MS->Sections,
+                    [](MergeInputSection *Sec) { Sec->initOffsetMap(); });
+  }
 
   std::vector<InputSectionBase *> &V = InputSections;
   V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
@@ -2572,8 +2599,7 @@
 // address described by any other table entry.
 void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
   assert(Highest);
-  uint64_t S =
-      Highest->getParent()->Addr + Highest->getOffset(Highest->getSize());
+  uint64_t S = Highest->getVA(Highest->getSize());
   uint64_t P = getVA();
   Target->relocateOne(Buf, R_ARM_PREL31, S - P);
   write32le(Buf + 4, 1);
@@ -2595,16 +2621,13 @@
 }
 
 void ThunkSection::addThunk(Thunk *T) {
-  uint64_t Off = alignTo(Size, T->Alignment);
-  T->Offset = Off;
   Thunks.push_back(T);
   T->addSymbols(*this);
-  Size = Off + T->size();
 }
 
 void ThunkSection::writeTo(uint8_t *Buf) {
-  for (const Thunk *T : Thunks)
-    T->writeTo(Buf + T->Offset, *this);
+  for (Thunk *T : Thunks)
+    T->writeTo(Buf + T->Offset);
 }
 
 InputSection *ThunkSection::getTargetInputSection() const {
@@ -2614,6 +2637,20 @@
   return T->getTargetInputSection();
 }
 
+bool ThunkSection::assignOffsets() {
+  uint64_t Off = 0;
+  for (Thunk *T : Thunks) {
+    Off = alignTo(Off, T->Alignment);
+    T->setOffset(Off);
+    uint32_t Size = T->size();
+    T->getThunkTargetSym()->Size = Size;
+    Off += Size;
+  }
+  bool Changed = Off != Size;
+  Size = Off;
+  return Changed;
+}
+
 InputSection *InX::ARMAttributes;
 BssSection *InX::Bss;
 BssSection *InX::BssRelRo;
diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h
index 855b91d..b709f4b 100644
--- a/ELF/SyntheticSections.h
+++ b/ELF/SyntheticSections.h
@@ -30,6 +30,7 @@
 
 namespace lld {
 namespace elf {
+class Defined;
 class SharedSymbol;
 
 class SyntheticSection : public InputSection {
@@ -83,6 +84,7 @@
   };
 
   std::vector<FdeData> getFdeData() const;
+  ArrayRef<CieRecord *> getCieRecords() const { return CieRecords; }
 
 private:
   uint64_t Size = 0;
@@ -269,7 +271,7 @@
   void addEntry(Symbol &Sym);
   size_t getSize() const override;
   void writeTo(uint8_t *Buf) override;
-  bool empty() const override { return Entries.empty(); }
+  bool empty() const override;
 
 private:
   std::vector<const Symbol *> Entries;
@@ -470,7 +472,7 @@
   void addSymbols(std::vector<SymbolTableEntry> &Symbols);
 
 private:
-  size_t getShift2() const { return Config->Is64 ? 6 : 5; }
+  enum { Shift2 = 6 };
 
   void writeBloomFilter(uint8_t *Buf);
   void writeHashTable(uint8_t *Buf);
@@ -683,13 +685,12 @@
 class MergeSyntheticSection : public SyntheticSection {
 public:
   void addSection(MergeInputSection *MS);
+  std::vector<MergeInputSection *> Sections;
 
 protected:
   MergeSyntheticSection(StringRef Name, uint32_t Type, uint64_t Flags,
                         uint32_t Alignment)
       : SyntheticSection(Flags, Type, Alignment, Name) {}
-
-  std::vector<MergeInputSection *> Sections;
 };
 
 class MergeTailSection final : public MergeSyntheticSection {
@@ -823,9 +824,10 @@
   size_t getSize() const override { return Size; }
   void writeTo(uint8_t *Buf) override;
   InputSection *getTargetInputSection() const;
+  bool assignOffsets();
 
 private:
-  std::vector<const Thunk *> Thunks;
+  std::vector<Thunk *> Thunks;
   size_t Size = 0;
 };
 
@@ -834,8 +836,8 @@
 void decompressSections();
 void mergeSections();
 
-Symbol *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
-                          uint64_t Size, InputSectionBase &Section);
+Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
+                           uint64_t Size, InputSectionBase &Section);
 
 // Linker generated sections which can be used as inputs.
 struct InX {
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index b528fd5..c19cb5f 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -87,7 +87,7 @@
   fatal("unknown target machine");
 }
 
-template <class ELFT> static std::string getErrorLoc(const uint8_t *Loc) {
+template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *Loc) {
   for (InputSectionBase *D : InputSections) {
     auto *IS = dyn_cast<InputSection>(D);
     if (!IS || !IS->getParent())
@@ -95,21 +95,21 @@
 
     uint8_t *ISLoc = IS->getParent()->Loc + IS->OutSecOff;
     if (ISLoc <= Loc && Loc < ISLoc + IS->getSize())
-      return IS->template getLocation<ELFT>(Loc - ISLoc) + ": ";
+      return {IS, IS->template getLocation<ELFT>(Loc - ISLoc) + ": "};
   }
-  return "";
+  return {};
 }
 
-std::string elf::getErrorLocation(const uint8_t *Loc) {
+ErrorPlace elf::getErrorPlace(const uint8_t *Loc) {
   switch (Config->EKind) {
   case ELF32LEKind:
-    return getErrorLoc<ELF32LE>(Loc);
+    return getErrPlace<ELF32LE>(Loc);
   case ELF32BEKind:
-    return getErrorLoc<ELF32BE>(Loc);
+    return getErrPlace<ELF32BE>(Loc);
   case ELF64LEKind:
-    return getErrorLoc<ELF64LE>(Loc);
+    return getErrPlace<ELF64LE>(Loc);
   case ELF64BEKind:
-    return getErrorLoc<ELF64BE>(Loc);
+    return getErrPlace<ELF64BE>(Loc);
   default:
     llvm_unreachable("unknown ELF type");
   }
diff --git a/ELF/Target.h b/ELF/Target.h
index 1f58adb..698758e 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -28,6 +28,7 @@
   virtual bool isPicRel(RelType Type) const { return true; }
   virtual RelType getDynRel(RelType Type) const { return Type; }
   virtual void writeGotPltHeader(uint8_t *Buf) const {}
+  virtual void writeGotHeader(uint8_t *Buf) const {}
   virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {};
   virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const;
   virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const;
@@ -43,6 +44,10 @@
   virtual void addPltHeaderSymbols(InputSection &IS) const {}
   virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {}
 
+  unsigned getPltEntryOffset(unsigned Index) const {
+    return Index * PltEntrySize + PltHeaderSize;
+  }
+
   // Returns true if a relocation only uses the low bits of a value such that
   // all those bits are in in the same page. For example, if the relocation
   // only uses the low 12 bits in a system with 4k pages. If this is true, the
@@ -71,9 +76,10 @@
 
   uint64_t getImageBase();
 
-  // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for
-  // end of .got
+  // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got or .got.plt section.
   uint64_t GotBaseSymOff = 0;
+  // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got.
+  bool GotBaseSymInGotPlt = true;
 
   // On systems with range extensions we place collections of Thunks at
   // regular spacings that enable the majority of branches reach the Thunks.
@@ -97,6 +103,9 @@
   // to support lazy loading.
   unsigned GotPltHeaderEntriesNum = 3;
 
+  // On PPC ELF V2 abi, the first entry in the .got is the .TOC.
+  unsigned GotHeaderEntriesNum = 0;
+
   // Set to 0 for variant 2
   unsigned TcbSize = 0;
 
@@ -134,7 +143,17 @@
 TargetInfo *getX86_64TargetInfo();
 template <class ELFT> TargetInfo *getMipsTargetInfo();
 
-std::string getErrorLocation(const uint8_t *Loc);
+struct ErrorPlace {
+  InputSectionBase *IS;
+  std::string Loc;
+};
+
+// Returns input section and corresponding source string for the given location.
+ErrorPlace getErrorPlace(const uint8_t *Loc);
+
+static inline std::string getErrorLocation(const uint8_t *Loc) {
+  return getErrorPlace(Loc).Loc;
+}
 
 uint64_t getPPC64TocBase();
 uint64_t getAArch64Page(uint64_t Expr);
@@ -146,39 +165,74 @@
 
 static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V,
                                     int64_t Min, uint64_t Max) {
-  error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) +
-        " out of range: " + V + " is not in [" + Twine(Min) + ", " +
-        Twine(Max) + "]");
+  ErrorPlace ErrPlace = getErrorPlace(Loc);
+  StringRef Hint;
+  if (ErrPlace.IS && ErrPlace.IS->Name.startswith(".debug"))
+    Hint = "; consider recompiling with -fdebug-types-section to reduce size "
+           "of debug sections";
+
+  error(ErrPlace.Loc + "relocation " + lld::toString(Type) +
+        " out of range: " + V.str() + " is not in [" + Twine(Min).str() + ", " +
+        Twine(Max).str() + "]" + Hint);
 }
 
-template <unsigned N>
-static void checkInt(uint8_t *Loc, int64_t V, RelType Type) {
-  if (!llvm::isInt<N>(V))
+// Sign-extend Nth bit all the way to MSB.
+inline int64_t signExtend(uint64_t V, int N) {
+  return int64_t(V << (64 - N)) >> (64 - N);
+}
+
+// Make sure that V can be represented as an N bit signed integer.
+inline void checkInt(uint8_t *Loc, int64_t V, int N, RelType Type) {
+  if (V != signExtend(V, N))
     reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N));
 }
 
-template <unsigned N>
-static void checkUInt(uint8_t *Loc, uint64_t V, RelType Type) {
-  if (!llvm::isUInt<N>(V))
+// Make sure that V can be represented as an N bit unsigned integer.
+inline void checkUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {
+  if ((V >> N) != 0)
     reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N));
 }
 
-template <unsigned N>
-static void checkIntUInt(uint8_t *Loc, uint64_t V, RelType Type) {
-  if (!llvm::isInt<N>(V) && !llvm::isUInt<N>(V))
-    // For the error message we should cast V to a signed integer so that error
-    // messages show a small negative value rather than an extremely large one
+// Make sure that V can be represented as an N bit signed or unsigned integer.
+inline void checkIntUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {
+  // For the error message we should cast V to a signed integer so that error
+  // messages show a small negative value rather than an extremely large one
+  if (V != (uint64_t)signExtend(V, N) && (V >> N) != 0)
     reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N),
-                     llvm::maxUIntN(N));
+                     llvm::maxIntN(N));
 }
 
-template <unsigned N>
-static void checkAlignment(uint8_t *Loc, uint64_t V, RelType Type) {
+inline void checkAlignment(uint8_t *Loc, uint64_t V, int N, RelType Type) {
   if ((V & (N - 1)) != 0)
     error(getErrorLocation(Loc) + "improper alignment for relocation " +
           lld::toString(Type) + ": 0x" + llvm::utohexstr(V) +
           " is not aligned to " + Twine(N) + " bytes");
 }
+
+// Endianness-aware read/write.
+inline uint16_t read16(const void *P) {
+  return llvm::support::endian::read16(P, Config->Endianness);
+}
+
+inline uint32_t read32(const void *P) {
+  return llvm::support::endian::read32(P, Config->Endianness);
+}
+
+inline uint64_t read64(const void *P) {
+  return llvm::support::endian::read64(P, Config->Endianness);
+}
+
+inline void write16(void *P, uint16_t V) {
+  llvm::support::endian::write16(P, V, Config->Endianness);
+}
+
+inline void write32(void *P, uint32_t V) {
+  llvm::support::endian::write32(P, V, Config->Endianness);
+}
+
+inline void write64(void *P, uint64_t V) {
+  llvm::support::endian::write64(P, V, Config->Endianness);
+}
 } // namespace elf
 } // namespace lld
 
diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp
index b0bbf6d..4db4990 100644
--- a/ELF/Thunks.cpp
+++ b/ELF/Thunks.cpp
@@ -40,7 +40,6 @@
 
 using namespace llvm;
 using namespace llvm::object;
-using namespace llvm::support::endian;
 using namespace llvm::ELF;
 
 namespace lld {
@@ -52,59 +51,112 @@
 class AArch64ABSLongThunk final : public Thunk {
 public:
   AArch64ABSLongThunk(Symbol &Dest) : Thunk(Dest) {}
-  uint32_t size() const override { return 16; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t size() override { return 16; }
+  void writeTo(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
 };
 
 class AArch64ADRPThunk final : public Thunk {
 public:
   AArch64ADRPThunk(Symbol &Dest) : Thunk(Dest) {}
-  uint32_t size() const override { return 12; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t size() override { return 12; }
+  void writeTo(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
 };
 
+// Base class for ARM thunks.
+//
+// An ARM thunk may be either short or long. A short thunk is simply a branch
+// (B) instruction, and it may be used to call ARM functions when the distance
+// from the thunk to the target is less than 32MB. Long thunks can branch to any
+// virtual address and can switch between ARM and Thumb, and they are
+// implemented in the derived classes. This class tries to create a short thunk
+// if the target is in range, otherwise it creates a long thunk.
+class ARMThunk : public Thunk {
+public:
+  ARMThunk(Symbol &Dest) : Thunk(Dest) {}
+
+  bool mayUseShortThunk();
+  uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
+  void writeTo(uint8_t *Buf) override;
+  bool isCompatibleWith(RelType Type) const override;
+
+  // Returns the size of a long thunk.
+  virtual uint32_t sizeLong() = 0;
+
+  // Writes a long thunk to Buf.
+  virtual void writeLong(uint8_t *Buf) = 0;
+
+private:
+  // This field tracks whether all previously considered layouts would allow
+  // this thunk to be short. If we have ever needed a long thunk, we always
+  // create a long thunk, even if the thunk may be short given the current
+  // distance to the target. We do this because transitioning from long to short
+  // can create layout oscillations in certain corner cases which would prevent
+  // the layout from converging.
+  bool MayUseShortThunk = true;
+};
+
+// Base class for Thumb-2 thunks.
+//
+// This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
+// which has a range of 16MB.
+class ThumbThunk : public Thunk {
+public:
+  ThumbThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+
+  bool mayUseShortThunk();
+  uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
+  void writeTo(uint8_t *Buf) override;
+  bool isCompatibleWith(RelType Type) const override;
+
+  // Returns the size of a long thunk.
+  virtual uint32_t sizeLong() = 0;
+
+  // Writes a long thunk to Buf.
+  virtual void writeLong(uint8_t *Buf) = 0;
+
+private:
+  // See comment in ARMThunk above.
+  bool MayUseShortThunk = true;
+};
+
 // Specific ARM Thunk implementations. The naming convention is:
 // Source State, TargetState, Target Requirement, ABS or PI, Range
-class ARMV7ABSLongThunk final : public Thunk {
+class ARMV7ABSLongThunk final : public ARMThunk {
 public:
-  ARMV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) {}
+  ARMV7ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {}
 
-  uint32_t size() const override { return 12; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t sizeLong() override { return 12; }
+  void writeLong(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
-  bool isCompatibleWith(RelType Type) const override;
 };
 
-class ARMV7PILongThunk final : public Thunk {
+class ARMV7PILongThunk final : public ARMThunk {
 public:
-  ARMV7PILongThunk(Symbol &Dest) : Thunk(Dest) {}
+  ARMV7PILongThunk(Symbol &Dest) : ARMThunk(Dest) {}
 
-  uint32_t size() const override { return 16; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t sizeLong() override { return 16; }
+  void writeLong(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
-  bool isCompatibleWith(RelType Type) const override;
 };
 
-class ThumbV7ABSLongThunk final : public Thunk {
+class ThumbV7ABSLongThunk final : public ThumbThunk {
 public:
-  ThumbV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+  ThumbV7ABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {}
 
-  uint32_t size() const override { return 10; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t sizeLong() override { return 10; }
+  void writeLong(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
-  bool isCompatibleWith(RelType Type) const override;
 };
 
-class ThumbV7PILongThunk final : public Thunk {
+class ThumbV7PILongThunk final : public ThumbThunk {
 public:
-  ThumbV7PILongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+  ThumbV7PILongThunk(Symbol &Dest) : ThumbThunk(Dest) {}
 
-  uint32_t size() const override { return 12; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t sizeLong() override { return 12; }
+  void writeLong(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
-  bool isCompatibleWith(RelType Type) const override;
 };
 
 // MIPS LA25 thunk
@@ -112,8 +164,8 @@
 public:
   MipsThunk(Symbol &Dest) : Thunk(Dest) {}
 
-  uint32_t size() const override { return 16; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t size() override { return 16; }
+  void writeTo(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
   InputSection *getTargetInputSection() const override;
 };
@@ -123,8 +175,8 @@
 public:
   MicroMipsThunk(Symbol &Dest) : Thunk(Dest) {}
 
-  uint32_t size() const override { return 14; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t size() override { return 14; }
+  void writeTo(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
   InputSection *getTargetInputSection() const override;
 };
@@ -134,14 +186,27 @@
 public:
   MicroMipsR6Thunk(Symbol &Dest) : Thunk(Dest) {}
 
-  uint32_t size() const override { return 12; }
-  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  uint32_t size() override { return 12; }
+  void writeTo(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
   InputSection *getTargetInputSection() const override;
 };
 
 } // end anonymous namespace
 
+Defined *Thunk::addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
+                          InputSectionBase &Section) {
+  Defined *D = addSyntheticLocal(Name, Type, Value, /*Size=*/0, Section);
+  Syms.push_back(D);
+  return D;
+}
+
+void Thunk::setOffset(uint64_t NewOffset) {
+  for (Defined *D : Syms)
+    D->Value = D->Value - Offset + NewOffset;
+  Offset = NewOffset;
+}
+
 // AArch64 long range Thunks
 
 static uint64_t getAArch64ThunkDestVA(const Symbol &S) {
@@ -149,7 +214,7 @@
   return V;
 }
 
-void AArch64ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void AArch64ABSLongThunk::writeTo(uint8_t *Buf) {
   const uint8_t Data[] = {
     0x50, 0x00, 0x00, 0x58, //     ldr x16, L0
     0x00, 0x02, 0x1f, 0xd6, //     br  x16
@@ -162,11 +227,10 @@
 }
 
 void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__AArch64AbsLongThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
-  addSyntheticLocal("$d", STT_NOTYPE, Offset + 8, 0, IS);
+  addSymbol(Saver.save("__AArch64AbsLongThunk_" + Destination.getName()),
+            STT_FUNC, 0, IS);
+  addSymbol("$x", STT_NOTYPE, 0, IS);
+  addSymbol("$d", STT_NOTYPE, 8, IS);
 }
 
 // This Thunk has a maximum range of 4Gb, this is sufficient for all programs
@@ -174,26 +238,24 @@
 // clang and gcc do not support the large code model for position independent
 // code so it is safe to use this for position independent thunks without
 // worrying about the destination being more than 4Gb away.
-void AArch64ADRPThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void AArch64ADRPThunk::writeTo(uint8_t *Buf) {
   const uint8_t Data[] = {
       0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)
       0x10, 0x02, 0x00, 0x91, // add  x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
       0x00, 0x02, 0x1f, 0xd6, // br   x16
   };
   uint64_t S = getAArch64ThunkDestVA(Destination);
-  uint64_t P = ThunkSym->getVA();
+  uint64_t P = getThunkTargetSym()->getVA();
   memcpy(Buf, Data, sizeof(Data));
   Target->relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21,
                       getAArch64Page(S) - getAArch64Page(P));
   Target->relocateOne(Buf + 4, R_AARCH64_ADD_ABS_LO12_NC, S);
 }
 
-void AArch64ADRPThunk::addSymbols(ThunkSection &IS)
-{
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$x", STT_NOTYPE, Offset, 0, IS);
+void AArch64ADRPThunk::addSymbols(ThunkSection &IS) {
+  addSymbol(Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,
+            0, IS);
+  addSymbol("$x", STT_NOTYPE, 0, IS);
 }
 
 // ARM Target Thunks
@@ -202,7 +264,81 @@
   return SignExtend64<32>(V);
 }
 
-void ARMV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+// This function returns true if the target is not Thumb and is within 2^26, and
+// it has not previously returned false (see comment for MayUseShortThunk).
+bool ARMThunk::mayUseShortThunk() {
+  if (!MayUseShortThunk)
+    return false;
+  uint64_t S = getARMThunkDestVA(Destination);
+  if (S & 1) {
+    MayUseShortThunk = false;
+    return false;
+  }
+  uint64_t P = getThunkTargetSym()->getVA();
+  int64_t Offset = S - P - 8;
+  MayUseShortThunk = llvm::isInt<26>(Offset);
+  return MayUseShortThunk;
+}
+
+void ARMThunk::writeTo(uint8_t *Buf) {
+  if (!mayUseShortThunk()) {
+    writeLong(Buf);
+    return;
+  }
+
+  uint64_t S = getARMThunkDestVA(Destination);
+  uint64_t P = getThunkTargetSym()->getVA();
+  int64_t Offset = S - P - 8;
+  const uint8_t Data[] = {
+    0x00, 0x00, 0x00, 0xea, // b S
+  };
+  memcpy(Buf, Data, sizeof(Data));
+  Target->relocateOne(Buf, R_ARM_JUMP24, Offset);
+}
+
+bool ARMThunk::isCompatibleWith(RelType Type) const {
+  // Thumb branch relocations can't use BLX
+  return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
+}
+
+// This function returns true if the target is Thumb and is within 2^25, and
+// it has not previously returned false (see comment for MayUseShortThunk).
+bool ThumbThunk::mayUseShortThunk() {
+  if (!MayUseShortThunk)
+    return false;
+  uint64_t S = getARMThunkDestVA(Destination);
+  if ((S & 1) == 0) {
+    MayUseShortThunk = false;
+    return false;
+  }
+  uint64_t P = getThunkTargetSym()->getVA() & ~1;
+  int64_t Offset = S - P - 4;
+  MayUseShortThunk = llvm::isInt<25>(Offset);
+  return MayUseShortThunk;
+}
+
+void ThumbThunk::writeTo(uint8_t *Buf) {
+  if (!mayUseShortThunk()) {
+    writeLong(Buf);
+    return;
+  }
+
+  uint64_t S = getARMThunkDestVA(Destination);
+  uint64_t P = getThunkTargetSym()->getVA();
+  int64_t Offset = S - P - 4;
+  const uint8_t Data[] = {
+      0x00, 0xf0, 0x00, 0xb0, // b.w S
+  };
+  memcpy(Buf, Data, sizeof(Data));
+  Target->relocateOne(Buf, R_ARM_THM_JUMP24, Offset);
+}
+
+bool ThumbThunk::isCompatibleWith(RelType Type) const {
+  // ARM branch relocations can't use BLX
+  return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
+}
+
+void ARMV7ABSLongThunk::writeLong(uint8_t *Buf) {
   const uint8_t Data[] = {
       0x00, 0xc0, 0x00, 0xe3, // movw         ip,:lower16:S
       0x00, 0xc0, 0x40, 0xe3, // movt         ip,:upper16:S
@@ -215,18 +351,12 @@
 }
 
 void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
+  addSymbol(Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()),
+            STT_FUNC, 0, IS);
+  addSymbol("$a", STT_NOTYPE, 0, IS);
 }
 
-bool ARMV7ABSLongThunk::isCompatibleWith(RelType Type) const {
-  // Thumb branch relocations can't use BLX
-  return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
-}
-
-void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void ThumbV7ABSLongThunk::writeLong(uint8_t *Buf) {
   const uint8_t Data[] = {
       0x40, 0xf2, 0x00, 0x0c, // movw         ip, :lower16:S
       0xc0, 0xf2, 0x00, 0x0c, // movt         ip, :upper16:S
@@ -239,18 +369,12 @@
 }
 
 void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), STT_FUNC,
-      Offset | 0x1, size(), IS);
-  addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
+  addSymbol(Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()),
+            STT_FUNC, 1, IS);
+  addSymbol("$t", STT_NOTYPE, 0, IS);
 }
 
-bool ThumbV7ABSLongThunk::isCompatibleWith(RelType Type) const {
-  // ARM branch relocations can't use BLX
-  return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
-}
-
-void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void ARMV7PILongThunk::writeLong(uint8_t *Buf) {
   const uint8_t Data[] = {
       0xf0, 0xcf, 0x0f, 0xe3, // P:  movw ip,:lower16:S - (P + (L1-P) + 8)
       0x00, 0xc0, 0x40, 0xe3, //     movt ip,:upper16:S - (P + (L1-P) + 8)
@@ -258,7 +382,7 @@
       0x1c, 0xff, 0x2f, 0xe1, //     bx r12
   };
   uint64_t S = getARMThunkDestVA(Destination);
-  uint64_t P = ThunkSym->getVA();
+  uint64_t P = getThunkTargetSym()->getVA();
   uint64_t Offset = S - P - 16;
   memcpy(Buf, Data, sizeof(Data));
   Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, Offset);
@@ -266,18 +390,12 @@
 }
 
 void ARMV7PILongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,
-      Offset, size(), IS);
-  addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, IS);
+  addSymbol(Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,
+            0, IS);
+  addSymbol("$a", STT_NOTYPE, 0, IS);
 }
 
-bool ARMV7PILongThunk::isCompatibleWith(RelType Type) const {
-  // Thumb branch relocations can't use BLX
-  return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
-}
-
-void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
+void ThumbV7PILongThunk::writeLong(uint8_t *Buf) {
   const uint8_t Data[] = {
       0x4f, 0xf6, 0xf4, 0x7c, // P:  movw ip,:lower16:S - (P + (L1-P) + 4)
       0xc0, 0xf2, 0x00, 0x0c, //     movt ip,:upper16:S - (P + (L1-P) + 4)
@@ -285,7 +403,7 @@
       0x60, 0x47,             //     bx   r12
   };
   uint64_t S = getARMThunkDestVA(Destination);
-  uint64_t P = ThunkSym->getVA() & ~0x1;
+  uint64_t P = getThunkTargetSym()->getVA() & ~0x1;
   uint64_t Offset = S - P - 12;
   memcpy(Buf, Data, sizeof(Data));
   Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, Offset);
@@ -293,32 +411,25 @@
 }
 
 void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym = addSyntheticLocal(
-      Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), STT_FUNC,
-      Offset | 0x1, size(), IS);
-  addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, IS);
-}
-
-bool ThumbV7PILongThunk::isCompatibleWith(RelType Type) const {
-  // ARM branch relocations can't use BLX
-  return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
+  addSymbol(Saver.save("__ThumbV7PILongThunk_" + Destination.getName()),
+            STT_FUNC, 1, IS);
+  addSymbol("$t", STT_NOTYPE, 0, IS);
 }
 
 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
-void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+void MipsThunk::writeTo(uint8_t *Buf) {
   uint64_t S = Destination.getVA();
-  write32(Buf, 0x3c190000, Config->Endianness); // lui   $25, %hi(func)
-  write32(Buf + 4, 0x08000000 | (S >> 2), Config->Endianness); // j     func
-  write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func)
-  write32(Buf + 12, 0x00000000, Config->Endianness); // nop
+  write32(Buf, 0x3c190000); // lui   $25, %hi(func)
+  write32(Buf + 4, 0x08000000 | (S >> 2)); // j     func
+  write32(Buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
+  write32(Buf + 12, 0x00000000); // nop
   Target->relocateOne(Buf, R_MIPS_HI16, S);
   Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
 }
 
 void MipsThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym =
-      addSyntheticLocal(Saver.save("__LA25Thunk_" + Destination.getName()),
-                        STT_FUNC, Offset, size(), IS);
+  addSymbol(Saver.save("__LA25Thunk_" + Destination.getName()), STT_FUNC, 0,
+            IS);
 }
 
 InputSection *MipsThunk::getTargetInputSection() const {
@@ -328,22 +439,21 @@
 
 // Write microMIPS R2-R5 LA25 thunk code
 // to call PIC function from the non-PIC one.
-void MicroMipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+void MicroMipsThunk::writeTo(uint8_t *Buf) {
   uint64_t S = Destination.getVA() | 1;
-  write16(Buf, 0x41b9, Config->Endianness);       // lui   $25, %hi(func)
-  write16(Buf + 4, 0xd400, Config->Endianness);   // j     func
-  write16(Buf + 8, 0x3339, Config->Endianness);   // addiu $25, $25, %lo(func)
-  write16(Buf + 12, 0x0c00, Config->Endianness);  // nop
+  write16(Buf, 0x41b9);       // lui   $25, %hi(func)
+  write16(Buf + 4, 0xd400);   // j     func
+  write16(Buf + 8, 0x3339);   // addiu $25, $25, %lo(func)
+  write16(Buf + 12, 0x0c00);  // nop
   Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
   Target->relocateOne(Buf + 4, R_MICROMIPS_26_S1, S);
   Target->relocateOne(Buf + 8, R_MICROMIPS_LO16, S);
 }
 
 void MicroMipsThunk::addSymbols(ThunkSection &IS) {
-  ThunkSym =
-      addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
-                        STT_FUNC, Offset, size(), IS);
-  ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+  Defined *D = addSymbol(
+      Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);
+  D->StOther |= STO_MIPS_MICROMIPS;
 }
 
 InputSection *MicroMipsThunk::getTargetInputSection() const {
@@ -353,22 +463,21 @@
 
 // Write microMIPS R6 LA25 thunk code
 // to call PIC function from the non-PIC one.
-void MicroMipsR6Thunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+void MicroMipsR6Thunk::writeTo(uint8_t *Buf) {
   uint64_t S = Destination.getVA() | 1;
-  uint64_t P = ThunkSym->getVA();
-  write16(Buf, 0x1320, Config->Endianness);       // lui   $25, %hi(func)
-  write16(Buf + 4, 0x3339, Config->Endianness);   // addiu $25, $25, %lo(func)
-  write16(Buf + 8, 0x9400, Config->Endianness);   // bc    func
+  uint64_t P = getThunkTargetSym()->getVA();
+  write16(Buf, 0x1320);       // lui   $25, %hi(func)
+  write16(Buf + 4, 0x3339);   // addiu $25, $25, %lo(func)
+  write16(Buf + 8, 0x9400);   // bc    func
   Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
   Target->relocateOne(Buf + 4, R_MICROMIPS_LO16, S);
   Target->relocateOne(Buf + 8, R_MICROMIPS_PC26_S1, S - P - 12);
 }
 
 void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) {
-  ThunkSym =
-      addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
-                        STT_FUNC, Offset, size(), IS);
-  ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+  Defined *D = addSymbol(
+      Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);
+  D->StOther |= STO_MIPS_MICROMIPS;
 }
 
 InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
diff --git a/ELF/Thunks.h b/ELF/Thunks.h
index 828fac0..ed82b4d 100644
--- a/ELF/Thunks.h
+++ b/ELF/Thunks.h
@@ -14,6 +14,7 @@
 
 namespace lld {
 namespace elf {
+class Defined;
 class Symbol;
 class ThunkSection;
 // Class to describe an instance of a Thunk.
@@ -30,12 +31,17 @@
   Thunk(Symbol &Destination);
   virtual ~Thunk();
 
-  virtual uint32_t size() const { return 0; }
-  virtual void writeTo(uint8_t *Buf, ThunkSection &IS) const {}
+  virtual uint32_t size() = 0;
+  virtual void writeTo(uint8_t *Buf) = 0;
 
-  // All Thunks must define at least one symbol ThunkSym so that we can
-  // redirect relocations to it.
-  virtual void addSymbols(ThunkSection &IS) {}
+  // All Thunks must define at least one symbol, known as the thunk target
+  // symbol, so that we can redirect relocations to it. The thunk may define
+  // additional symbols, but these are never targets for relocations.
+  virtual void addSymbols(ThunkSection &IS) = 0;
+
+  void setOffset(uint64_t Offset);
+  Defined *addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
+                     InputSectionBase &Section);
 
   // Some Thunks must be placed immediately before their Target as they elide
   // a branch and fall through to the first Symbol in the Target.
@@ -45,10 +51,12 @@
   // compatible with it.
   virtual bool isCompatibleWith(RelType Type) const { return true; }
 
+  Defined *getThunkTargetSym() const { return Syms[0]; }
+
   // The alignment requirement for this Thunk, defaults to the size of the
   // typical code section alignment.
   Symbol &Destination;
-  Symbol *ThunkSym;
+  llvm::SmallVector<Defined *, 3> Syms;
   uint64_t Offset = 0;
   uint32_t Alignment = 4;
 };
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 309022d..e685c8e 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -62,7 +62,7 @@
   void assignFileOffsets();
   void assignFileOffsetsBinary();
   void setPhdrs();
-  void checkNoOverlappingSections();
+  void checkSectionOverlap();
   void fixSectionAlignments();
   void openFile();
   void writeTrapInstr();
@@ -94,13 +94,13 @@
   // This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want
   // to emit .rela.text.foo as .rela.text.bar for consistency (this is not
   // technically required, but not doing it is odd). This code guarantees that.
-  if ((S->Type == SHT_REL || S->Type == SHT_RELA) &&
-      !isa<SyntheticSection>(S)) {
-    OutputSection *Out =
-        cast<InputSection>(S)->getRelocatedSection()->getOutputSection();
-    if (S->Type == SHT_RELA)
-      return Saver.save(".rela" + Out->Name);
-    return Saver.save(".rel" + Out->Name);
+  if (auto *IS = dyn_cast<InputSection>(S)) {
+    if (InputSectionBase *Rel = IS->getRelocatedSection()) {
+      OutputSection *Out = Rel->getOutputSection();
+      if (S->Type == SHT_RELA)
+        return Saver.save(".rela" + Out->Name);
+      return Saver.save(".rel" + Out->Name);
+    }
   }
 
   for (StringRef V :
@@ -190,21 +190,29 @@
           Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
   }
 
+  // The 64-bit PowerOpen ABI defines a TableOfContents (TOC) which combines the
+  // typical ELF GOT with the small data sections. It commonly includes .got
+  // .toc .sdata .sbss. The .TOC. symbol replaces both _GLOBAL_OFFSET_TABLE_ and
+  // _SDA_BASE_ from the 32-bit ABI. It is used to represent the TOC base which
+  // is offset by 0x8000 bytes from the start of the .got section.
   ElfSym::GlobalOffsetTable = addOptionalRegular(
-      "_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff);
+      (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_",
+      Out::ElfHeader, Target->GotBaseSymOff);
 
   // __ehdr_start is the location of ELF file headers. Note that we define
   // this symbol unconditionally even when using a linker script, which
   // differs from the behavior implemented by GNU linker which only define
   // this symbol if ELF headers are in the memory mapped segment.
+  addOptionalRegular("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);
+
   // __executable_start is not documented, but the expectation of at
-  // least the android libc is that it points to the elf header too.
+  // least the Android libc is that it points to the ELF header.
+  addOptionalRegular("__executable_start", Out::ElfHeader, 0, STV_HIDDEN);
+
   // __dso_handle symbol is passed to cxa_finalize as a marker to identify
   // each DSO. The address of the symbol doesn't matter as long as they are
   // different in different DSOs, so we chose the start address of the DSO.
-  for (const char *Name :
-       {"__ehdr_start", "__executable_start", "__dso_handle"})
-    addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN);
+  addOptionalRegular("__dso_handle", Out::ElfHeader, 0, STV_HIDDEN);
 
   // If linker script do layout we do not need to create any standart symbols.
   if (Script->HasSectionsCommand)
@@ -276,10 +284,9 @@
   // If there is a SECTIONS command and a .data.rel.ro section name use name
   // .data.rel.ro.bss so that we match in the .data.rel.ro output section.
   // This makes sure our relro is contiguous.
-  bool HasDataRelRo =
-      Script->HasSectionsCommand && findSection(".data.rel.ro");
-  InX::BssRelRo = make<BssSection>(
-      HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
+  bool HasDataRelRo = Script->HasSectionsCommand && findSection(".data.rel.ro");
+  InX::BssRelRo =
+      make<BssSection>(HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
   Add(InX::BssRelRo);
 
   // Add MIPS-specific sections.
@@ -451,7 +458,7 @@
   }
 
   if (Config->CheckSections)
-    checkNoOverlappingSections();
+    checkSectionOverlap();
 
   // It does not make sense try to open the file if we have error already.
   if (errorCount())
@@ -475,8 +482,9 @@
   if (errorCount())
     return;
 
-  // Handle -Map option.
+  // Handle -Map and -cref options.
   writeMapFile();
+  writeCrossReferenceTable();
   if (errorCount())
     return;
 
@@ -868,11 +876,12 @@
 // defining these symbols explicitly in the linker script.
 template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
   if (ElfSym::GlobalOffsetTable) {
-    // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to
-    // be at some offset from the base of the .got section, usually 0 or the end
-    // of the .got
-    InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot)
-                                            : cast<InputSection>(InX::Got);
+    // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually
+    // to the start of the .got or .got.plt section.
+    InputSection *GotSection = InX::GotPlt;
+    if (!Target->GotBaseSymInGotPlt)
+      GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot)
+                                : cast<InputSection>(InX::Got);
     ElfSym::GlobalOffsetTable->Section = GotSection;
   }
 
@@ -1187,7 +1196,7 @@
   auto E = Script->SectionCommands.end();
   auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) {
     if (auto *Sec = dyn_cast<OutputSection>(Base))
-      return Sec->SectionIndex == INT_MAX;
+      return Sec->SectionIndex == UINT32_MAX;
     return false;
   });
 
@@ -1621,8 +1630,8 @@
   StringRef S = Sec->Name;
   if (!isValidCIdentifier(S))
     return;
-  addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
-  addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
+  addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_PROTECTED);
+  addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_PROTECTED);
 }
 
 static bool needsPtLoad(OutputSection *Sec) {
@@ -1750,11 +1759,9 @@
   // pages for the stack non-executable. If you really want an executable
   // stack, you can pass -z execstack, but that's not recommended for
   // security reasons.
-  unsigned Perm;
+  unsigned Perm = PF_R | PF_W;
   if (Config->ZExecstack)
-    Perm = PF_R | PF_W | PF_X;
-  else
-    Perm = PF_R | PF_W;
+    Perm |= PF_X;
   AddHdr(PT_GNU_STACK, Perm)->p_memsz = Config->ZStackSize;
 
   // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable
@@ -1872,6 +1879,12 @@
   FileSize = alignTo(Off, Config->Wordsize);
 }
 
+static std::string rangeToString(uint64_t Addr, uint64_t Len) {
+  if (Len == 0)
+    return "<empty range at 0x" + utohexstr(Addr) + ">";
+  return "[0x" + utohexstr(Addr) + ", 0x" + utohexstr(Addr + Len - 1) + "]";
+}
+
 // Assign file offsets to output sections.
 template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
   uint64_t Off = 0;
@@ -1896,6 +1909,25 @@
 
   SectionHeaderOff = alignTo(Off, Config->Wordsize);
   FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
+
+  // Our logic assumes that sections have rising VA within the same segment.
+  // With use of linker scripts it is possible to violate this rule and get file
+  // offset overlaps or overflows. That should never happen with a valid script
+  // which does not move the location counter backwards and usually scripts do
+  // not do that. Unfortunately, there are apps in the wild, for example, Linux
+  // kernel, which control segment distribution explicitly and move the counter
+  // backwards, so we have to allow doing that to support linking them. We
+  // perform non-critical checks for overlaps in checkNoOverlappingSections(),
+  // but here we want to prevent file size overflows because it would crash the
+  // linker.
+  for (OutputSection *Sec : OutputSections) {
+    if (Sec->Type == SHT_NOBITS)
+      continue;
+    if ((Sec->Offset > FileSize) || (Sec->Offset + Sec->Size > FileSize))
+      error("unable to place section " + Sec->Name + " at file offset " +
+            rangeToString(Sec->Offset, Sec->Offset + Sec->Size) +
+            "; check your linker script for overflows");
+  }
 }
 
 // Finalize the program headers. We call this function after we assign
@@ -1934,55 +1966,33 @@
   }
 }
 
-static std::string rangeToString(uint64_t Addr, uint64_t Len) {
-  if (Len == 0)
-    return "<empty range at 0x" + utohexstr(Addr) + ">";
-  return "[0x" + utohexstr(Addr) + " -> 0x" + utohexstr(Addr + Len - 1) + "]";
-}
+// A helper struct for checkSectionOverlap.
+namespace {
+struct SectionOffset {
+  OutputSection *Sec;
+  uint64_t Offset;
+};
+} // namespace
 
 // Check whether sections overlap for a specific address range (file offsets,
 // load and virtual adresses).
-//
-// This is a helper function called by Writer::checkNoOverlappingSections().
-template <typename Getter, typename Predicate>
-static void checkForSectionOverlap(ArrayRef<OutputSection *> AllSections,
-                                   StringRef Kind, Getter GetStart,
-                                   Predicate ShouldSkip) {
-  std::vector<OutputSection *> Sections;
-  // By removing all zero-size sections we can simplify the check for overlap to
-  // just checking whether the section range contains the other section's start
-  // address. Additionally, it also slightly speeds up the checking since we
-  // don't bother checking for overlap with sections that can never overlap.
-  for (OutputSection *Sec : AllSections)
-    if (Sec->Size > 0 && !ShouldSkip(Sec))
-      Sections.push_back(Sec);
-
-  // Instead of comparing every OutputSection with every other output section
-  // we sort the sections by address (file offset or load/virtual address). This
-  // way we find all overlapping sections but only need one comparision with the
-  // next section in the common non-overlapping case. The only time we end up
-  // doing more than one iteration of the following nested loop is if there are
-  // overlapping sections.
+static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections) {
   std::sort(Sections.begin(), Sections.end(),
-            [=](const OutputSection *A, const OutputSection *B) {
-              return GetStart(A) < GetStart(B);
+            [=](const SectionOffset &A, const SectionOffset &B) {
+              return A.Offset < B.Offset;
             });
-  for (size_t I = 0; I < Sections.size(); ++I) {
-    OutputSection *Sec = Sections[I];
-    uint64_t Start = GetStart(Sec);
-    for (auto *Other : ArrayRef<OutputSection *>(Sections).slice(I + 1)) {
-      // Since the sections are sorted by start address we only need to check
-      // whether the other sections starts before the end of Sec. If this is
-      // not the case we can break out of this loop since all following sections
-      // will also start after the end of Sec.
-      if (Start + Sec->Size <= GetStart(Other))
-        break;
-      errorOrWarn("section " + Sec->Name + " " + Kind +
-                  " range overlaps with " + Other->Name + "\n>>> " + Sec->Name +
-                  " range is " + rangeToString(Start, Sec->Size) + "\n>>> " +
-                  Other->Name + " range is " +
-                  rangeToString(GetStart(Other), Other->Size));
-    }
+
+  // Finding overlap is easy given a vector is sorted by start position.
+  // If an element starts before the end of the previous element, they overlap.
+  for (size_t I = 1, End = Sections.size(); I < End; ++I) {
+    SectionOffset A = Sections[I - 1];
+    SectionOffset B = Sections[I];
+    if (B.Offset < A.Offset + A.Sec->Size)
+      errorOrWarn(
+          "section " + A.Sec->Name + " " + Name + " range overlaps with " +
+          B.Sec->Name + "\n>>> " + A.Sec->Name + " range is " +
+          rangeToString(A.Offset, A.Sec->Size) + "\n>>> " + B.Sec->Name +
+          " range is " + rangeToString(B.Offset, B.Sec->Size));
   }
 }
 
@@ -1991,18 +2001,18 @@
 // In this function we check that none of the output sections have overlapping
 // file offsets. For SHF_ALLOC sections we also check that the load address
 // ranges and the virtual address ranges don't overlap
-template <class ELFT> void Writer<ELFT>::checkNoOverlappingSections() {
+template <class ELFT> void Writer<ELFT>::checkSectionOverlap() {
   // First check for overlapping file offsets. In this case we need to skip
-  // Any section marked as SHT_NOBITS. These sections don't actually occupy
+  // any section marked as SHT_NOBITS. These sections don't actually occupy
   // space in the file so Sec->Offset + Sec->Size can overlap with others.
   // If --oformat binary is specified only add SHF_ALLOC sections are added to
   // the output file so we skip any non-allocated sections in that case.
-  checkForSectionOverlap(
-      OutputSections, "file", [](const OutputSection *Sec) { return Sec->Offset; },
-      [](const OutputSection *Sec) {
-        return Sec->Type == SHT_NOBITS ||
-               (Config->OFormatBinary && (Sec->Flags & SHF_ALLOC) == 0);
-      });
+  std::vector<SectionOffset> FileOffs;
+  for (OutputSection *Sec : OutputSections)
+    if (0 < Sec->Size && Sec->Type != SHT_NOBITS &&
+        (!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC)))
+      FileOffs.push_back({Sec, Sec->Offset});
+  checkOverlap("file", FileOffs);
 
   // When linking with -r there is no need to check for overlapping virtual/load
   // addresses since those addresses will only be assigned when the final
@@ -2015,19 +2025,20 @@
   // Furthermore, we also need to skip SHF_TLS sections since these will be
   // mapped to other addresses at runtime and can therefore have overlapping
   // ranges in the file.
-  auto SkipNonAllocSections = [](const OutputSection *Sec) {
-    return (Sec->Flags & SHF_ALLOC) == 0 || (Sec->Flags & SHF_TLS);
-  };
-  checkForSectionOverlap(OutputSections, "virtual address",
-                         [](const OutputSection *Sec) { return Sec->Addr; },
-                         SkipNonAllocSections);
+  std::vector<SectionOffset> VMAs;
+  for (OutputSection *Sec : OutputSections)
+    if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+      VMAs.push_back({Sec, Sec->Addr});
+  checkOverlap("virtual address", VMAs);
 
   // Finally, check that the load addresses don't overlap. This will usually be
   // the same as the virtual addresses but can be different when using a linker
   // script with AT().
-  checkForSectionOverlap(OutputSections, "load address",
-                         [](const OutputSection *Sec) { return Sec->getLMA(); },
-                         SkipNonAllocSections);
+  std::vector<SectionOffset> LMAs;
+  for (OutputSection *Sec : OutputSections)
+    if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+      LMAs.push_back({Sec, Sec->getLMA()});
+  checkOverlap("load address", LMAs);
 }
 
 // The entry point address is chosen in the following ways.
@@ -2072,17 +2083,19 @@
 }
 
 static uint8_t getAbiVersion() {
-  if (Config->EMachine == EM_MIPS) {
-    // Increment the ABI version for non-PIC executable files.
-    if (getELFType() == ET_EXEC &&
-        (Config->EFlags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
-      return 1;
-  }
+  // MIPS non-PIC executable gets ABI version 1.
+  if (Config->EMachine == EM_MIPS && getELFType() == ET_EXEC &&
+      (Config->EFlags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
+    return 1;
   return 0;
 }
 
 template <class ELFT> void Writer<ELFT>::writeHeader() {
   uint8_t *Buf = Buffer->getBufferStart();
+  // For executable segments, the trap instructions are written before writing
+  // the header. Setting Elf header bytes to zero ensures that any unused bytes
+  // in header are zero-cleared, instead of having trap instructions.
+  memset(Buf, 0, sizeof(Elf_Ehdr));
   memcpy(Buf, "\177ELF", 4);
 
   // Write the ELF header.
diff --git a/MinGW/Driver.cpp b/MinGW/Driver.cpp
index 6d3bea5..0b7e083 100644
--- a/MinGW/Driver.cpp
+++ b/MinGW/Driver.cpp
@@ -154,6 +154,8 @@
     Add("-debug:dwarf");
   if (Args.hasArg(OPT_large_address_aware))
     Add("-largeaddressaware");
+  if (Args.hasArg(OPT_kill_at))
+    Add("-kill-at");
 
   if (Args.getLastArgValue(OPT_m) != "thumb2pe" &&
       Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase))
diff --git a/MinGW/Options.td b/MinGW/Options.td
index 4213b8e..6840471 100644
--- a/MinGW/Options.td
+++ b/MinGW/Options.td
@@ -14,6 +14,7 @@
 def gc_sections: F<"gc-sections">, HelpText<"Remove unused sections">;
 def icf: J<"icf=">, HelpText<"Identical code folding">;
 def image_base: S<"image-base">, HelpText<"Base address of the program">;
+def kill_at: F<"kill-at">, HelpText<"Remove @n from exported symbols">;
 def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
   HelpText<"Root name of library to use">;
 def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
diff --git a/cmake/modules/AddLLD.cmake b/cmake/modules/AddLLD.cmake
index 0d95179..fa48b42 100644
--- a/cmake/modules/AddLLD.cmake
+++ b/cmake/modules/AddLLD.cmake
@@ -10,7 +10,7 @@
   llvm_add_library(${name} ${ARG_ENABLE_SHARED} ${ARG_UNPARSED_ARGUMENTS})
   set_target_properties(${name} PROPERTIES FOLDER "lld libraries")
 
-  if (LLD_BUILD_TOOLS)
+  if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
     if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
         NOT LLVM_DISTRIBUTION_COMPONENTS)
       set(export_to_lldtargets EXPORT lldTargets)
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 3b07a40..4617d23 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -906,7 +906,7 @@
   abbrevData.getU8(&abbrevOffset);
   uint32_t name;
   llvm::dwarf::Form form;
-  llvm::DWARFFormParams formParams = {version, addrSize, Format};
+  llvm::dwarf::FormParams formParams = {version, addrSize, Format};
   TranslationUnitSource tu;
   while ((name = abbrevData.getULEB128(&abbrevOffset)) |
          (form = static_cast<llvm::dwarf::Form>(
diff --git a/test/COFF/Inputs/generic.yaml b/test/COFF/Inputs/generic.yaml
new file mode 100644
index 0000000..88c8765
--- /dev/null
+++ b/test/COFF/Inputs/generic.yaml
@@ -0,0 +1,282 @@
+--- !COFF
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       16
+    SectionData:     4883EC1831C0C7442414000000004889542408894C24044883C418C3
+  - Name:            .data
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4
+    SectionData:     ''
+  - Name:            .bss
+    Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4
+    SectionData:     ''
+  - Name:            .xdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     '0104010004220000'
+  - Name:            .drectve
+    Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+    Alignment:       1
+    SectionData:     202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962
+  - Name:            '.debug$S'
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     04000000F10000002F0000002D003C1101000000D0000700000000000000581B000000000000636C616E672076657273696F6E20372E302E30200000F1000000760000002A0047110000000000000000000000001C000000000000000000000003100000000000000000006D61696E000D003E117400000001006172676300120045114F0100000400000017000000000005000D003E110010000001006172677600120045114F01000008000000170000000000050002004F110000F20000002800000000000000000000001C00000000000000020000001C00000000000000020000001700000003000000F40000001800000001000000100139E9A066A1995A99DD01F5A392F26D7C0000F30000003000000000443A5C7372635C6C6C766D6275696C645C636C5C52656C656173655C7836345C67656E657269632E63707000000000
+    Subsections:
+      - !Symbols
+        Records:
+          - Kind:            S_COMPILE3
+            Compile3Sym:
+              Flags:           [  ]
+              Machine:         X64
+              FrontendMajor:   7
+              FrontendMinor:   0
+              FrontendBuild:   0
+              FrontendQFE:     0
+              BackendMajor:    7000
+              BackendMinor:    0
+              BackendBuild:    0
+              BackendQFE:      0
+              Version:         'clang version 7.0.0 '
+      - !Symbols
+        Records:
+          - Kind:            S_GPROC32_ID
+            ProcSym:
+              CodeSize:        28
+              DbgStart:        0
+              DbgEnd:          0
+              FunctionType:    4099
+              Flags:           [  ]
+              DisplayName:     main
+          - Kind:            S_LOCAL
+            LocalSym:
+              Type:            116
+              Flags:           [ IsParameter ]
+              VarName:         argc
+          - Kind:            S_DEFRANGE_REGISTER_REL
+            DefRangeRegisterRelSym:
+              Register:        335
+              Flags:           0
+              BasePointerOffset: 4
+              Range:
+                OffsetStart:     23
+                ISectStart:      0
+                Range:           5
+              Gaps:
+          - Kind:            S_LOCAL
+            LocalSym:
+              Type:            4096
+              Flags:           [ IsParameter ]
+              VarName:         argv
+          - Kind:            S_DEFRANGE_REGISTER_REL
+            DefRangeRegisterRelSym:
+              Register:        335
+              Flags:           0
+              BasePointerOffset: 8
+              Range:
+                OffsetStart:     23
+                ISectStart:      0
+                Range:           5
+              Gaps:
+          - Kind:            S_PROC_ID_END
+            ScopeEndSym:
+      - !Lines
+        CodeSize:        28
+        Flags:           [  ]
+        RelocOffset:     0
+        RelocSegment:    0
+        Blocks:
+          - FileName:        'D:\src\llvmbuild\cl\Release\x64\generic.cpp'
+            Lines:
+              - Offset:          0
+                LineStart:       2
+                IsStatement:     false
+                EndDelta:        0
+              - Offset:          23
+                LineStart:       3
+                IsStatement:     false
+                EndDelta:        0
+            Columns:
+      - !FileChecksums
+        Checksums:
+          - FileName:        'D:\src\llvmbuild\cl\Release\x64\generic.cpp'
+            Kind:            MD5
+            Checksum:        39E9A066A1995A99DD01F5A392F26D7C
+      - !StringTable
+        Strings:
+          - 'D:\src\llvmbuild\cl\Release\x64\generic.cpp'
+          - ''
+          - ''
+          - ''
+    Relocations:
+      - VirtualAddress:  100
+        SymbolName:      main
+        Type:            IMAGE_REL_AMD64_SECREL
+      - VirtualAddress:  104
+        SymbolName:      main
+        Type:            IMAGE_REL_AMD64_SECTION
+      - VirtualAddress:  139
+        SymbolName:      .text
+        Type:            IMAGE_REL_AMD64_SECREL
+      - VirtualAddress:  143
+        SymbolName:      .text
+        Type:            IMAGE_REL_AMD64_SECTION
+      - VirtualAddress:  174
+        SymbolName:      .text
+        Type:            IMAGE_REL_AMD64_SECREL
+      - VirtualAddress:  178
+        SymbolName:      .text
+        Type:            IMAGE_REL_AMD64_SECTION
+      - VirtualAddress:  196
+        SymbolName:      main
+        Type:            IMAGE_REL_AMD64_SECREL
+      - VirtualAddress:  200
+        SymbolName:      main
+        Type:            IMAGE_REL_AMD64_SECTION
+  - Name:            '.debug$T'
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     040000000A000210700600000C0001000E0001120200000074000000001000000E0008107400000000000200011000001200011600000000021000006D61696E00F3F2F1
+    Types:
+      - Kind:            LF_POINTER
+        Pointer:
+          ReferentType:    1648
+          Attrs:           65548
+      - Kind:            LF_ARGLIST
+        ArgList:
+          ArgIndices:      [ 116, 4096 ]
+      - Kind:            LF_PROCEDURE
+        Procedure:
+          ReturnType:      116
+          CallConv:        NearC
+          Options:         [ None ]
+          ParameterCount:  2
+          ArgumentList:    4097
+      - Kind:            LF_FUNC_ID
+        FuncId:
+          ParentScope:     0
+          FunctionType:    4098
+          Name:            main
+  - Name:            .pdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     000000001C00000000000000
+    Relocations:
+      - VirtualAddress:  0
+        SymbolName:      main
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  4
+        SymbolName:      main
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  8
+        SymbolName:      .xdata
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          28
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        594448369
+      Number:          1
+  - Name:            .data
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          0
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          2
+  - Name:            .bss
+    Value:           0
+    SectionNumber:   3
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          0
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          3
+  - Name:            .xdata
+    Value:           0
+    SectionNumber:   4
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          8
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        1192424177
+      Number:          4
+  - Name:            .drectve
+    Value:           0
+    SectionNumber:   5
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          48
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        149686238
+      Number:          5
+  - Name:            '.debug$S'
+    Value:           0
+    SectionNumber:   6
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          324
+      NumberOfRelocations: 8
+      NumberOfLinenumbers: 0
+      CheckSum:        4196717433
+      Number:          6
+  - Name:            '.debug$T'
+    Value:           0
+    SectionNumber:   7
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          68
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        485351071
+      Number:          7
+  - Name:            .pdata
+    Value:           0
+    SectionNumber:   8
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          12
+      NumberOfRelocations: 3
+      NumberOfLinenumbers: 0
+      CheckSum:        722740324
+      Number:          8
+  - Name:            main
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/loadconfig-cfg-x64.s b/test/COFF/Inputs/loadconfig-cfg-x64.s
new file mode 100644
index 0000000..1440b11
--- /dev/null
+++ b/test/COFF/Inputs/loadconfig-cfg-x64.s
@@ -0,0 +1,11 @@
+# This is the _load_config_used definition needed for /guard:cf tests.
+
+        .section .rdata,"dr"
+.globl _load_config_used
+_load_config_used:
+        .long 256
+        .fill 124, 1, 0
+        .quad __guard_fids_table
+        .quad __guard_fids_count
+        .long __guard_flags
+        .fill 128, 1, 0
diff --git a/test/COFF/Inputs/natvis-1.natvis b/test/COFF/Inputs/natvis-1.natvis
new file mode 100644
index 0000000..8797a36
--- /dev/null
+++ b/test/COFF/Inputs/natvis-1.natvis
@@ -0,0 +1 @@
+1st Natvis Test
diff --git a/test/COFF/Inputs/natvis-2.natvis b/test/COFF/Inputs/natvis-2.natvis
new file mode 100644
index 0000000..50ba443
--- /dev/null
+++ b/test/COFF/Inputs/natvis-2.natvis
@@ -0,0 +1 @@
+Second Natvis Test
diff --git a/test/COFF/Inputs/natvis-3.natvis b/test/COFF/Inputs/natvis-3.natvis
new file mode 100644
index 0000000..a10b1a1
--- /dev/null
+++ b/test/COFF/Inputs/natvis-3.natvis
@@ -0,0 +1 @@
+Third Natvis Test
diff --git a/test/COFF/def-export-stdcall.s b/test/COFF/def-export-stdcall.s
index db25140..fd1ec2c 100644
--- a/test/COFF/def-export-stdcall.s
+++ b/test/COFF/def-export-stdcall.s
@@ -44,7 +44,8 @@
 # DECORATED-EXPORTS: Name: vectorcall@@8
 
 
-# RUN: echo -e "LIBRARY foo\nEXPORTS\n  stdcall@8\n  @fastcall@8" > %t.def
+# GNU tools don't support vectorcall at the moment, but test it for completeness.
+# RUN: echo -e "LIBRARY foo\nEXPORTS\n  stdcall@8\n  @fastcall@8\n  vectorcall@@8" > %t.def
 # RUN: lld-link -lldmingw -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
 # RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-MINGW-IMPLIB %s
 # RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix DECORATED-MINGW-EXPORTS %s
@@ -55,9 +56,39 @@
 # DECORATED-MINGW-IMPLIB: Name type: noprefix
 # DECORATED-MINGW-IMPLIB-NEXT: __imp__stdcall@8
 # DECORATED-MINGW-IMPLIB-NEXT: _stdcall@8
+# GNU tools don't support vectorcall, but this test is just to track that
+# lld's behaviour remains consistent over time.
+# DECORATED-MINGW-IMPLIB: Name type: name
+# DECORATED-MINGW-IMPLIB-NEXT: __imp_vectorcall@@8
+# DECORATED-MINGW-IMPLIB-NEXT: vectorcall@@8
 
 # DECORATED-MINGW-EXPORTS: Name: @fastcall@8
 # DECORATED-MINGW-EXPORTS: Name: stdcall@8
+# DECORATED-MINGW-EXPORTS: Name: vectorcall@@8
+
+# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s
+# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s
+
+# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll %t.obj -out:%t.dll -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s
+# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s
+
+# MINGW-KILL-AT-IMPLIB: Name type: noprefix
+# MINGW-KILL-AT-IMPLIB: __imp__fastcall
+# MINGW-KILL-AT-IMPLIB-NEXT: _fastcall
+# MINGW-KILL-AT-IMPLIB: Name type: noprefix
+# MINGW-KILL-AT-IMPLIB-NEXT: __imp__stdcall
+# MINGW-KILL-AT-IMPLIB-NEXT: _stdcall
+# GNU tools don't support vectorcall, but this test is just to track that
+# lld's behaviour remains consistent over time.
+# MINGW-KILL-AT-IMPLIB: Name type: noprefix
+# MINGW-KILL-AT-IMPLIB-NEXT: __imp__vectorcall
+# MINGW-KILL-AT-IMPLIB-NEXT: _vectorcall
+
+# MINGW-KILL-AT-EXPORTS: Name: fastcall
+# MINGW-KILL-AT-EXPORTS: Name: stdcall
+# MINGW-KILL-AT-EXPORTS: Name: vectorcall
 
 
         .def     _stdcall@8;
diff --git a/test/COFF/dll.test b/test/COFF/dll.test
index abd39f4..9bd8698 100644
--- a/test/COFF/dll.test
+++ b/test/COFF/dll.test
@@ -26,7 +26,7 @@
 EXPORT2-NEXT:       2   0x101c  mangled2
 
 # RUN: llvm-as -o %t.lto.obj %p/Inputs/export.ll
-# RUN: lld-link /out:%t.lto.dll /dll %t.lto.obj /export:exportfn1 /export:exportfn2
+# RUN: lld-link -opt:noicf /out:%t.lto.dll /dll %t.lto.obj /export:exportfn1 /export:exportfn2
 # RUN: llvm-objdump -p %t.lto.dll | FileCheck -check-prefix=EXPORT-LTO %s
 
 EXPORT-LTO:      Export Table:
diff --git a/test/COFF/error-limit.test b/test/COFF/error-limit.test
index 3eebd12..09c3b9d 100644
--- a/test/COFF/error-limit.test
+++ b/test/COFF/error-limit.test
@@ -3,27 +3,27 @@
 
 DEFAULT:      could not open 01
 DEFAULT:      could not open 20
-DEFAULT-NEXT: too many errors emitted, stopping now (use /ERRORLIMIT:0 to see all errors)
+DEFAULT-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
 DEFAULT-NOT:  could not open 21
 
-RUN: not lld-link /ERRORLIMIT:5 01 02 03 04 05 06 07 08 09 10 2>&1 \
+RUN: not lld-link /errorlimit:5 01 02 03 04 05 06 07 08 09 10 2>&1 \
 RUN:   | FileCheck -check-prefix=LIMIT5 %s
 
 LIMIT5:      could not open 01
 LIMIT5:      could not open 05
-LIMIT5-NEXT: too many errors emitted, stopping now (use /ERRORLIMIT:0 to see all errors)
+LIMIT5-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
 LIMIT5-NOT:  could not open 06
 
-RUN: not lld-link /ERRORLIMIT:0 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 \
+RUN: not lld-link /errorlimit:0 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 \
 RUN:   16 17 18 19 20 21 22 2>&1 | FileCheck -check-prefix=UNLIMITED %s
 
 UNLIMITED:     could not open 01
 UNLIMITED:     could not open 20
 UNLIMITED:     could not open 21
 UNLIMITED:     could not open 22
-UNLIMITED-NOT: too many errors emitted, stopping now (use /ERRORLIMIT:0 to see all errors)
+UNLIMITED-NOT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
 
-RUN: not lld-link /ERRORLIMIT:XYZ 01 02 03 04 05 06 07 08 09 10 11 12 13 14 \
+RUN: not lld-link /errorlimit:XYZ 01 02 03 04 05 06 07 08 09 10 11 12 13 14 \
 RUN:   15 16 17 18 19 20 21 22 2>&1 | FileCheck -check-prefix=WRONG %s
 
-WRONG:      /ERRORLIMIT: number expected, but got XYZ
+WRONG:      /errorlimit: number expected, but got XYZ
diff --git a/test/COFF/fixed.test b/test/COFF/fixed.test
new file mode 100644
index 0000000..6975fed
--- /dev/null
+++ b/test/COFF/fixed.test
@@ -0,0 +1,24 @@
+# REQUIRES: x86
+# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
+#
+# RUN: lld-link %t.obj /fixed %p/Inputs/std32.lib /subsystem:console \
+# RUN:   /entry:main@0 /debug /out:%t.fixed.exe
+# RUN: llvm-readobj -file-headers %t.fixed.exe | \
+# RUN:   FileCheck -check-prefix=EXEFIXED %s
+#
+# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
+# RUN:   /entry:main@0 /debug /out:%t.exe
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=EXEREL %s
+#
+# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
+#
+# RUN: lld-link %t.obj /dll /fixed /debug /out:%t.fixed.dll
+# RUN: llvm-readobj -file-headers %t.fixed.dll | FileCheck -check-prefix=DLLFIXED %s
+#
+# RUN: lld-link %t.obj /dll /debug /out:%t.dll
+# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=DLLREL %s
+
+EXEFIXED-NOT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
+DLLFIXED-NOT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
+EXEREL: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
+DLLREL: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
diff --git a/test/COFF/guardcf-lto.ll b/test/COFF/guardcf-lto.ll
new file mode 100644
index 0000000..8675117
--- /dev/null
+++ b/test/COFF/guardcf-lto.ll
@@ -0,0 +1,39 @@
+; Set up an import library for a DLL that will do the indirect call.
+; RUN: echo -e 'LIBRARY library\nEXPORTS\n  do_indirect_call\n' > %t.def
+; RUN: lld-link -lib -def:%t.def -out:%t.lib -machine:x64
+
+; Generate an object that will have the load configuration normally provided by
+; the CRT.
+; RUN: llvm-mc -triple x86_64-windows-msvc -filetype=obj %S/Inputs/loadconfig-cfg-x64.s -o %t.ldcfg.obj
+
+; RUN: llvm-as %s -o %t.bc
+; RUN: lld-link -entry:main -guard:cf -dll %t.bc %t.lib %t.ldcfg.obj -out:%t.dll
+; RUN: llvm-readobj -coff-load-config %t.dll | FileCheck %s
+
+; There must be *two* entries in the table: DLL entry point, and my_handler.
+
+; CHECK:      LoadConfig [
+; CHECK:        GuardCFFunctionTable: 0x{{[^0].*}}
+; CHECK-NEXT:   GuardCFFunctionCount: 2
+; CHECK-NEXT:   GuardFlags: 0x10500
+; CHECK:      ]
+; CHECK:      GuardFidTable [
+; CHECK-NEXT:   0x180{{.*}}
+; CHECK-NEXT:   0x180{{.*}}
+; CHECK-NEXT: ]
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.12.25835"
+
+declare dllimport void @do_indirect_call(void ()*)
+
+define dso_local i32 @main() local_unnamed_addr {
+entry:
+  tail call void @do_indirect_call(void ()* nonnull @my_handler)
+  ret i32 0
+}
+
+define dso_local void @my_handler() {
+entry:
+  ret void
+}
diff --git a/test/COFF/hello32.test b/test/COFF/hello32.test
index 2399193..9f3cadc 100644
--- a/test/COFF/hello32.test
+++ b/test/COFF/hello32.test
@@ -11,7 +11,7 @@
 HEADER-NEXT: ImageFileHeader {
 HEADER-NEXT:   Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
 HEADER-NEXT:   SectionCount: 4
-HEADER-NEXT:   TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+HEADER-NEXT:   TimeDateStamp: 
 HEADER-NEXT:   PointerToSymbolTable: 0x0
 HEADER-NEXT:   SymbolCount: 0
 HEADER-NEXT:   OptionalHeaderSize: 224
@@ -40,7 +40,7 @@
 HEADER-NEXT:   MajorSubsystemVersion: 6
 HEADER-NEXT:   MinorSubsystemVersion: 0
 HEADER-NEXT:   SizeOfImage: 20480
-HEADER-NEXT:   SizeOfHeaders: 512
+HEADER-NEXT:   SizeOfHeaders: 1024
 HEADER-NEXT:   Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
 HEADER-NEXT:   Characteristics [ (0x9540)
 HEADER-NEXT:     IMAGE_DLL_CHARACTERISTICS_APPCONTAINER (0x1000)
@@ -91,10 +91,10 @@
 HEADER-NEXT: }
 HEADER-NEXT: DOSHeader {
 HEADER-NEXT:   Magic: MZ
-HEADER-NEXT:   UsedBytesInTheLastPage: 0
-HEADER-NEXT:   FileSizeInPages: 0
+HEADER-NEXT:   UsedBytesInTheLastPage: 120
+HEADER-NEXT:   FileSizeInPages: 1
 HEADER-NEXT:   NumberOfRelocationItems: 0
-HEADER-NEXT:   HeaderSizeInParagraphs: 0
+HEADER-NEXT:   HeaderSizeInParagraphs: 4
 HEADER-NEXT:   MinimumExtraParagraphs: 0
 HEADER-NEXT:   MaximumExtraParagraphs: 0
 HEADER-NEXT:   InitialRelativeSS: 0
@@ -106,7 +106,7 @@
 HEADER-NEXT:   OverlayNumber: 0
 HEADER-NEXT:   OEMid: 0
 HEADER-NEXT:   OEMinfo: 0
-HEADER-NEXT:   AddressOfNewExeHeader: 64
+HEADER-NEXT:   AddressOfNewExeHeader: 120
 HEADER-NEXT: }
 
 IMPORTS: Format: COFF-i386
diff --git a/test/COFF/icf-simple.test b/test/COFF/icf-simple.test
index ead7e76..19f13c6 100644
--- a/test/COFF/icf-simple.test
+++ b/test/COFF/icf-simple.test
@@ -23,6 +23,11 @@
 # RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
 # RUN: FileCheck -check-prefix=NOICF %s < %t.log
 
+# /profile disables ICF.
+# RUN: lld-link /profile /entry:foo /out:%t.exe /subsystem:console \
+# RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=NOICF %s < %t.log
+
 # /opt:noref disables ICF.
 # RUN: lld-link /opt:noref /entry:foo /out:%t.exe /subsystem:console \
 # RUN:   /include:bar /verbose %t.obj > %t.log 2>&1
diff --git a/test/COFF/incremental.test b/test/COFF/incremental.test
index d5a5ba8..01f2748 100644
--- a/test/COFF/incremental.test
+++ b/test/COFF/incremental.test
@@ -1,4 +1,5 @@
 # RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
+
 # RUN: lld-link -out:%t.dll -dll %t.obj 2>&1 \
 # RUN:   | FileCheck -allow-empty -check-prefix=NOWARN %s
 # RUN: touch -t 198002011200.00 %t.lib
@@ -11,6 +12,12 @@
 # RUN: lld-link -out:%t.dll -dll -incremental %t.obj
 # RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s
 
+# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,noicf %t.obj 2>&1 \
+# RUN:   | FileCheck -allow-empty -check-prefix=NOWARN %s
+# RUN: touch -t 198002011200.00 %t.lib
+# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,noicf %t.obj
+# RUN: ls -l %t.lib | FileCheck -check-prefix=KEEP %s
+
 # RUN: lld-link -out:%t.dll -dll -debug %t.obj 2>&1 \
 # RUN:   | FileCheck -allow-empty -check-prefix=NOWARN %s
 # RUN: touch -t 198002011200.00 %t.lib
@@ -53,14 +60,41 @@
 # RUN: lld-link -out:%t.dll -dll -incremental -opt:ref %t.obj
 # RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s
 
+# RUN: touch %t.order
+# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,noicf %t.obj \
+# RUN:   -order:@%t.order 2>&1 | FileCheck -check-prefix=WARN-ORDER %s
+# RUN: touch -t 198002011200.00 %t.lib
+# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,noicf -order:@%t.order %t.obj
+# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s
+
+# RUN: lld-link -out:%t.dll -dll -opt:noref,noicf %t.obj \
+# RUN:   -order:@%t.order 2>&1 | FileCheck -allow-empty -check-prefix=NOWARN %s
+# RUN: touch -t 198002011200.00 %t.lib
+# RUN: lld-link -out:%t.dll -dll -opt:noref,noicf -order:@%t.order %t.obj
+# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s
+
+# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,noicf %t.obj \
+# RUN:   -profile 2>&1 | FileCheck -check-prefix=WARN-PROFILE %s
+# RUN: touch -t 198002011200.00 %t.lib
+# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,noicf -profile %t.obj
+# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s
+
+# RUN: lld-link -out:%t.dll -dll -opt:noref,noicf %t.obj \
+# RUN:   -profile 2>&1 | FileCheck -allow-empty -check-prefix=NOWARN %s
+# RUN: touch -t 198002011200.00 %t.lib
+# RUN: lld-link -out:%t.dll -dll -opt:noref,noicf -profile %t.obj
+# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s
+
 # RUN: lld-link -out:%t.dll -dll -debug -opt:ref %t.obj 2>&1 \
 # RUN:   | FileCheck -allow-empty -check-prefix=NOWARN %s
 # RUN: touch -t 198002011200.00 %t.lib
 # RUN: lld-link -out:%t.dll -dll -debug -opt:ref %t.obj
 # RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s
 
-# NOWARN-NOT: ignoring '/INCREMENTAL'
-# WARN-ICF: ignoring '/INCREMENTAL' because ICF is enabled; use '/OPT:NOICF' to disable
-# WARN-REF: ignoring '/INCREMENTAL' because REF is enabled; use '/OPT:NOREF' to disable
+# NOWARN-NOT: ignoring '/incremental'
+# WARN-ICF: ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to disable
+# WARN-REF: ignoring '/incremental' because REF is enabled; use '/opt:noref' to disable
+# WARN-ORDER: ignoring '/incremental' due to '/order' specification
+# WARN-PROFILE: ignoring '/incremental' due to '/profile' specification
 # KEEP: {{Feb 1 1980|1980-02-01}}
 # NOKEEP-NOT: {{Feb 1 1980|1980-02-01}}
diff --git a/test/COFF/largeaddressaware.test b/test/COFF/largeaddressaware.test
index d035e7c..76aadee 100644
--- a/test/COFF/largeaddressaware.test
+++ b/test/COFF/largeaddressaware.test
@@ -9,7 +9,7 @@
 HEADER-NEXT: ImageFileHeader {
 HEADER-NEXT:   Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
 HEADER-NEXT:   SectionCount: 4
-HEADER-NEXT:   TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+HEADER-NEXT:   TimeDateStamp: 
 HEADER-NEXT:   PointerToSymbolTable: 0x0
 HEADER-NEXT:   SymbolCount: 0
 HEADER-NEXT:   OptionalHeaderSize: 224
diff --git a/test/COFF/lto-comdat.ll b/test/COFF/lto-comdat.ll
index b255f69..9594d30 100644
--- a/test/COFF/lto-comdat.ll
+++ b/test/COFF/lto-comdat.ll
@@ -49,18 +49,17 @@
 ; TEXT-01: Disassembly of section .text:
 ; TEXT-01-NEXT: .text:
 ; TEXT-01-NEXT: subq	$40, %rsp
-; TEXT-01-NEXT: callq	39
-; TEXT-01-NEXT: callq	50
+; TEXT-01-NEXT: callq	23
+; TEXT-01-NEXT: callq	18
 ; TEXT-01-NEXT: callq	13
 ; TEXT-01-NEXT: xorl	%eax, %eax
 ; TEXT-01-NEXT: addq	$40, %rsp
 ; TEXT-01: retq
 ; TEXT-01-NOT: callq
 ; TEXT-01: retq
-; TEXT-01-NOT: callq
-; TEXT-01: retq
-; TEXT-01-NOT: callq
-; TEXT-01: retq
+; TEXT-01: int3
+; TEXT-01: int3
+; TEXT-01: int3
 ; TEXT-01-NOT: {{.}}
 
 ; HEADERS-10: AddressOfEntryPoint: 0x2020
diff --git a/test/COFF/lto-icf.ll b/test/COFF/lto-icf.ll
new file mode 100644
index 0000000..291188f
--- /dev/null
+++ b/test/COFF/lto-icf.ll
@@ -0,0 +1,26 @@
+; Test that ICF works after LTO, i.e. both functions have the same address.
+; Previously, when we didn't enable function sections, ICF didn't work.
+
+; RUN: llvm-as %s -o %t.bc
+; RUN: lld-link -opt:icf -dll -noentry %t.bc -out:%t.dll
+; RUN: llvm-readobj -coff-exports %t.dll | FileCheck %s
+
+; CHECK: Export {
+; CHECK: Export {
+; CHECK:   RVA: 0x[[RVA:.*]]
+; CHECK: Export {
+; CHECK:   RVA: 0x[[RVA]]
+; CHECK-NOT: Export
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.12.25835"
+
+define dllexport i8* @icf_ptr() {
+entry:
+  ret i8* null
+}
+
+define dllexport i64 @icf_int() {
+entry:
+  ret i64 0
+}
diff --git a/test/COFF/lto-parallel.ll b/test/COFF/lto-parallel.ll
index 449e3a0..df0dc25 100644
--- a/test/COFF/lto-parallel.ll
+++ b/test/COFF/lto-parallel.ll
@@ -1,11 +1,12 @@
 ; RUN: llvm-as -o %t.obj %s
-; RUN: lld-link /out:%t.exe /entry:foo /include:bar /opt:lldltopartitions=2 /subsystem:console /lldmap:%t.map %t.obj
+; RUN: lld-link -opt:noicf /out:%t.exe /entry:foo /include:bar /opt:lldltopartitions=2 /subsystem:console /lldmap:%t.map %t.obj
 ; RUN: FileCheck %s < %t.map
 
 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-windows-msvc"
 
 ; CHECK: lto.tmp
+; CHECK: lto.tmp
 ; CHECK-NEXT: foo
 define void @foo() {
   call void @bar()
@@ -13,6 +14,7 @@
 }
 
 ; CHECK: lto.tmp
+; CHECK: lto.tmp
 ; CHECK: bar
 define void @bar() {
   call void @foo()
diff --git a/test/COFF/opt.test b/test/COFF/opt.test
index a8b0e2e..ed43b60 100644
--- a/test/COFF/opt.test
+++ b/test/COFF/opt.test
@@ -1,18 +1,24 @@
 # RUN: yaml2obj < %s > %t.obj
 
 # RUN: lld-link /out:%t.exe /entry:main %t.obj \
-# RUN:   /verbose >& %t.log
-### FileCheck doesn't like empty input, so write something.
-# RUN: echo dummy >> %t.log
-# RUN: FileCheck -check-prefix=CHECK1 %s < %t.log
+# RUN:   /verbose 2>&1 | FileCheck -check-prefix=REF %s
+
+# /debug disables the /opt:ref default...
+# RUN: lld-link /out:%t.exe /debug /entry:main %t.obj \
+# RUN:   /verbose 2>&1 | FileCheck -check-prefix=NOREF %s
+
+# ...unless /profile is passed as well.
+# RUN: lld-link /out:%t.exe /profile /debug /entry:main %t.obj \
+# RUN:   /verbose 2>&1 | FileCheck -check-prefix=REF %s
+
+# RUN: lld-link /out:%t.exe /opt:ref /debug /entry:main %t.obj \
+# RUN:   /verbose 2>&1 | FileCheck -check-prefix=REF %s
 
 # RUN: lld-link /out:%t.exe /entry:main %t.obj \
-# RUN:   /verbose /opt:noref >& %t.log
-# RUN: echo dummy >> %t.log
-# RUN: FileCheck -check-prefix=CHECK2 %s < %t.log
+# RUN:   /verbose /opt:noref /profile 2>&1 | FileCheck -check-prefix=NOREF %s
 
-# CHECK1:     Discarded unused
-# CHECK2-NOT: Discarded unused
+# REF:       Discarded unused
+# NOREF-NOT: Discarded unused
 
 --- !COFF
 header:
diff --git a/test/COFF/order.test b/test/COFF/order.test
index a01f820..0006550 100644
--- a/test/COFF/order.test
+++ b/test/COFF/order.test
@@ -16,7 +16,7 @@
 # CHECK: unrelated2
 
 # RUN: lld-link -entry:fn1 -subsystem:console -opt:noref -debug %t1.obj %t2.obj \
-# RUN:   -lldmap:- -out:%t.exe | FileCheck -check-prefix=DEFAULT %s
+# RUN:   -lldmap:- -ignore:4037 -out:%t.exe | FileCheck -check-prefix=DEFAULT %s
 # DEFAULT: fn2
 # DEFAULT: fn3
 # DEFAULT: unrelated1
@@ -35,6 +35,13 @@
 # WARN-NOT: f2
 # WARN-NOT: f3
 # WARN-NOT: f4
+# RUN: lld-link -entry:fn1 -subsystem:console -debug %t1.obj %t2.obj \
+# RUN:   -out:%t.exe -order:@%t2.order -ignore:4037 2>&1 | \
+# RUN:   FileCheck -allow-empty -check-prefix=NOWARN %s
+# NOWARN-NOT: warning: /order:{{.*}} missing symbol: foo
+# NOWARN-NOT: f2
+# NOWARN-NOT: f3
+# NOWARN-NOT: f4
 
 --- !COFF
 header:
diff --git a/test/COFF/pdb-diff.test b/test/COFF/pdb-diff.test
deleted file mode 100644
index 17d26b6..0000000
--- a/test/COFF/pdb-diff.test
+++ /dev/null
@@ -1,215 +0,0 @@
-This test verifies that we produce PDBs compatible with MSVC in various ways.
-We check in a cl-generated object file, PDB, and original source which serve
-as the "baseline" for us to measure against.  Then we link the same object
-file with LLD and compare the two PDBs.  Since the baseline object file and
-PDB are already checked in, we just run LLD on the object file.
-
-RUN: rm -f %T/pdb-diff-lld.pdb %T/pdb-diff-lld.exe
-RUN: lld-link /debug /pdb:%T/pdb-diff-lld.pdb /out:%T/pdb-diff-lld.exe /nodefaultlib \
-RUN:   /entry:main %S/Inputs/pdb-diff.obj
-RUN: llvm-pdbutil diff -result -values=false -left-bin-root=%S -right-bin-root=D:/src/llvm-mono/lld/test/COFF/ \
-RUN:   %T/pdb-diff-lld.pdb %S/Inputs/pdb-diff-cl.pdb | FileCheck %s
-
-CHECK:        ----------------------
-CHECK-NEXT:   |  MSF Super Block   |
-CHECK-NEXT:   |----------------+---|
-CHECK-NEXT:   |           File |   |
-CHECK-NEXT:   |----------------+---|
-CHECK-NEXT:   |     Block Size | I |
-CHECK-NEXT:   |----------------+---|
-CHECK-NEXT:   |    Block Count |
-CHECK-NEXT:   |----------------+---|
-CHECK-NEXT:   |      Unknown 1 | I |
-CHECK-NEXT:   |----------------+---|
-CHECK-NEXT:   | Directory Size |
-CHECK-NEXT:   |----------------+---|
-CHECK-NEXT:   ------------------------------------
-CHECK-NEXT:   |         Stream Directory         |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                         File |   |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                 Stream Count | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |            Old MSF Directory | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                   PDB Stream | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                   TPI Stream | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                   DBI Stream | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                   IPI Stream | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                 New FPO Data | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |          Section Header Data | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |        Named Stream "/names" | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |     Named Stream "/LinkInfo" | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   | Module "Inputs\pdb-diff.obj" | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |          Module "* Linker *" | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                     TPI Hash | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                     IPI Hash | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |           Public Symbol Hash | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |           Global Symbol Hash | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |               Symbol Records | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   ------------------------------------
-CHECK-NEXT:   |           String Table           |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                         File |   |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |            Number of Strings | D |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                 Hash Version | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                    Byte Size |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                    Signature | I |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |                Empty Strings |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |  {{.*}}pdb-diff.cpp | {{[EI]}} |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |  $T0 $ebp = $...p $T0 8 + =  | D |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   |  d:\src\llvm-...er internal) | D |
-CHECK-NEXT:   |------------------------------+---|
-CHECK-NEXT:   ----------------------------
-CHECK-NEXT:   |        PDB Stream        |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |                 File |   |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |          Stream Size |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |                  Age | I |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |                 Guid | D |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |            Signature | D |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |              Version | I |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |       Features (set) | I |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |              Feature | I |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |    Named Stream Size |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |  Named Streams (map) | {{[EI]}} |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |               /names | {{[EI]}} |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   |            /LinkInfo | {{[EI]}} |
-CHECK-NEXT:   |----------------------+---|
-CHECK-NEXT:   ----------------------------------------------
-CHECK-NEXT:   |                 DBI Stream                 |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                                   File |   |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                            Dbi Version | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                                    Age | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                                Machine | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                                  Flags | D |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                            Build Major | D |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                            Build Minor | D |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                           Build Number | D |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        PDB DLL Version | D |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                           PDB DLL RBLD | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                              DBG (FPO) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        DBG (Exception) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                            DBG (Fixup) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        DBG (OmapToSrc) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                      DBG (OmapFromSrc) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                       DBG (SectionHdr) | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                      DBG (TokenRidMap) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                            DBG (Xdata) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                            DBG (Pdata) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                           DBG (NewFPO) | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                   DBG (SectionHdrOrig) | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                         Globals Stream | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                         Publics Stream | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                         Symbol Records | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                             Has CTypes | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                Is Incrementally Linked | D |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                            Is Stripped | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                           Module Count | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                      Source File Count | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   | Module "Inputs\pdb-diff.obj" |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                                 - Modi | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        - Obj File Name | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                         - Debug Stream | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        - C11 Byte Size | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        - C13 Byte Size | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                           - # of files | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                  - Pdb File Path Index | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |               - Source File Name Index | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                     - Symbol Byte Size |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |            Module "* Linker *"             |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                                 - Modi | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        - Obj File Name | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                         - Debug Stream | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        - C11 Byte Size | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                        - C13 Byte Size | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                           - # of files | I |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                  - Pdb File Path Index | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |               - Source File Name Index | {{[EI]}} |
-CHECK-NEXT:   |----------------------------------------+---|
-CHECK-NEXT:   |                     - Symbol Byte Size |
-CHECK-NEXT:   |----------------------------------------+---|
-
-
diff --git a/test/COFF/pdb-file-static.test b/test/COFF/pdb-file-static.test
index 1d09823..f08f717 100644
--- a/test/COFF/pdb-file-static.test
+++ b/test/COFF/pdb-file-static.test
@@ -43,9 +43,9 @@
 # CHECK: ============================================================
 # CHECK-LABEL:   Mod 0000 | `{{.*}}a.obj`:
 # CHECK:              232 | S_FILESTATIC [size = 16] `x`
-# CHECK-NEXT:               type = 0x0074 (int), file name = 1 (D:\src\llvmbuild\cl\Debug\x64\a.obj), flags = enreg global | enreg static
+# CHECK-NEXT:               type = 0x0074 (int), file name = 2 (D:\src\llvmbuild\cl\Debug\x64\a.obj), flags = enreg global | enreg static
 # CHECK:         Mod 0001 | `{{.*}}b.obj`:
 # CHECK:              232 | S_FILESTATIC [size = 16] `y`
-# CHECK-NEXT:               type = 0x0074 (int), file name = 73 (D:\src\llvmbuild\cl\Debug\x64\b.obj), flags = enreg global | enreg static
+# CHECK-NEXT:               type = 0x0074 (int), file name = 74 (D:\src\llvmbuild\cl\Debug\x64\b.obj), flags = enreg global | enreg static
 # CHECK-LABEL:   Mod 0002 | `* Linker *`:
 
diff --git a/test/COFF/pdb-lib.s b/test/COFF/pdb-lib.s
index 319d4bc..c970f0b 100644
--- a/test/COFF/pdb-lib.s
+++ b/test/COFF/pdb-lib.s
@@ -13,15 +13,15 @@
 # CHECK-NEXT: ============================================================
 # CHECK-NEXT:   Mod 0000 | `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`:
 # CHECK-NEXT:              Obj: `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`:
-# CHECK-NEXT:              debug stream: 9, # files: 0, has ec info: false
+# CHECK-NEXT:              debug stream: 10, # files: 0, has ec info: false
 # CHECK-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
 # CHECK-NEXT:   Mod 0001 | `bar.obj`:
 # CHECK-NEXT:              Obj: `{{.*pdb-lib.s.tmp[/\\]bar.lib}}`:
-# CHECK-NEXT:              debug stream: 10, # files: 0, has ec info: false
+# CHECK-NEXT:              debug stream: 11, # files: 0, has ec info: false
 # CHECK-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
 # CHECK-NEXT:   Mod 0002 | `* Linker *`:
 # CHECK-NEXT:              Obj: ``:
-# CHECK-NEXT:              debug stream: 11, # files: 0, has ec info: false
+# CHECK-NEXT:              debug stream: 12, # files: 0, has ec info: false
 # CHECK-NEXT:              pdb file ni: 1 `{{.*foo.pdb}}`, src file ni: 0 ``
 
         .def     _main;
diff --git a/test/COFF/pdb-linker-module.test b/test/COFF/pdb-linker-module.test
index 1bb5729..96ca1b4 100644
--- a/test/COFF/pdb-linker-module.test
+++ b/test/COFF/pdb-linker-module.test
@@ -4,7 +4,7 @@
 
 MODS:      Mod 0001 | `* Linker *`
 MODS-NEXT:             Obj: ``:
-MODS-NEXT:             debug stream: 10, # files: 0, has ec info: false
+MODS-NEXT:             debug stream: 12, # files: 0, has ec info: false
 MODS-NEXT:             pdb file ni: 1 `{{.*}}pdb-linker-module.test.tmp.pdb`, src file ni: 0 ``
 
 SYMS:      Mod 0001 | `* Linker *`
diff --git a/test/COFF/pdb-natvis.test b/test/COFF/pdb-natvis.test
new file mode 100644
index 0000000..2db68b6
--- /dev/null
+++ b/test/COFF/pdb-natvis.test
@@ -0,0 +1,26 @@
+REQUIRES: diasdk
+
+RUN: yaml2obj %p/Inputs/generic.yaml > %t.obj
+RUN: lld-link /DEBUG %t.obj /nodefaultlib /entry:main /NATVIS:%p/Inputs/natvis-1.natvis \
+RUN:   /NATVIS:%p/Inputs/natvis-2.natvis /NATVIS:%p/Inputs/natvis-3.natvis /OUT:%t.exe \
+RUN:   /PDB:%t.pdb
+RUN: llvm-pdbutil pretty -injected-sources -injected-source-content %t.pdb | FileCheck \
+RUN:   --check-prefix=CHECK-FIRST %s
+RUN: llvm-pdbutil pretty -injected-sources -injected-source-content %t.pdb | FileCheck \
+RUN:   --check-prefix=CHECK-SECOND %s
+RUN: llvm-pdbutil pretty -injected-sources -injected-source-content %t.pdb | FileCheck \
+RUN:   --check-prefix=CHECK-THIRD %s
+
+RUN: lld-link /DEBUG %t.obj /nodefaultlib /entry:main /NATVIS:%p/Inputs/test2.natvis \
+RUN:   /OUT:%t.exe /PDB:%t.pdb 2>&1 | FileCheck --check-prefix=CHECK-MISSING %s
+
+CHECK-FIRST:      {{.*}}natvis-1.natvis (16 bytes): obj=<null>, vname={{.*}}natvis-1.natvis, crc=355285096, compression=None
+CHECK-FIRST-NEXT: 1st Natvis Test
+
+CHECK-SECOND:      {{.*}}natvis-2.natvis (19 bytes): obj=<null>, vname={{.*}}natvis-2.natvis, crc=4252640062, compression=None
+CHECK-SECOND-NEXT: Second Natvis Test
+
+CHECK-THIRD:      {{.*}}natvis-3.natvis (18 bytes): obj=<null>, vname={{.*}}natvis-3.natvis, crc=2069719849, compression=None
+CHECK-THIRD-NEXT: Third Natvis Test
+
+CHECK-MISSING: Cannot open input file: {{.*}}test2.natvis
\ No newline at end of file
diff --git a/test/COFF/pdb-same-name.test b/test/COFF/pdb-same-name.test
index 76db69f..352bfc9 100644
--- a/test/COFF/pdb-same-name.test
+++ b/test/COFF/pdb-same-name.test
@@ -15,9 +15,9 @@
 RAW-NEXT: ============================================================
 RAW-NEXT:   Mod 0000 | `foo.obj`:
 RAW-NEXT:              Obj: `{{.*}}1\foo.lib`:
-RAW-NEXT:              debug stream: 9, # files: 1, has ec info: false
+RAW-NEXT:              debug stream: 11, # files: 1, has ec info: false
 RAW-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
 RAW-NEXT:   Mod 0001 | `foo.obj`:
 RAW-NEXT:              Obj: `{{.*}}2\foo.lib`:
-RAW-NEXT:              debug stream: 10, # files: 1, has ec info: false
+RAW-NEXT:              debug stream: 12, # files: 1, has ec info: false
 RAW-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
diff --git a/test/COFF/pdb.test b/test/COFF/pdb.test
index dad6de2..faab5fe 100644
--- a/test/COFF/pdb.test
+++ b/test/COFF/pdb.test
@@ -14,7 +14,7 @@
 # CHECK:      MSF:
 # CHECK-NEXT:   SuperBlock:
 # CHECK-NEXT:     BlockSize:       4096
-# CHECK-NEXT:     FreeBlockMap:    1
+# CHECK-NEXT:     FreeBlockMap:    2
 # CHECK-NEXT:     NumBlocks:
 # CHECK-NEXT:     NumDirectoryBytes:
 # CHECK-NEXT:     Unknown1:        0
@@ -121,15 +121,15 @@
 RAW-NEXT: ============================================================
 RAW-NEXT:   Mod 0000 | `{{.*}}pdb.test.tmp1.obj`:
 RAW-NEXT:              Obj: `{{.*}}pdb.test.tmp1.obj`:
-RAW-NEXT:              debug stream: 9, # files: 1, has ec info: false
+RAW-NEXT:              debug stream: 11, # files: 1, has ec info: false
 RAW-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
 RAW-NEXT:   Mod 0001 | `{{.*}}pdb.test.tmp2.obj`:
 RAW-NEXT:              Obj: `{{.*}}pdb.test.tmp2.obj`:
-RAW-NEXT:              debug stream: 10, # files: 1, has ec info: false
+RAW-NEXT:              debug stream: 12, # files: 1, has ec info: false
 RAW-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
 RAW-NEXT:   Mod 0002 | `* Linker *`:
 RAW-NEXT:              Obj: ``:
-RAW-NEXT:              debug stream: 11, # files: 0, has ec info: false
+RAW-NEXT:              debug stream: 13, # files: 0, has ec info: false
 RAW-NEXT:              pdb file ni: 1 `{{.*pdb.test.tmp.pdb}}`, src file ni: 0 ``
 RAW:                          Types (TPI Stream)
 RAW-NEXT: ============================================================
diff --git a/test/COFF/rsds.test b/test/COFF/rsds.test
index 1765977..10c2c56 100644
--- a/test/COFF/rsds.test
+++ b/test/COFF/rsds.test
@@ -18,7 +18,7 @@
 # CHECK: DebugDirectory [
 # CHECK:   DebugEntry {
 # CHECK:     Characteristics: 0x0
-# CHECK:     TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+# CHECK:     TimeDateStamp: 
 # CHECK:     MajorVersion: 0x0
 # CHECK:     MinorVersion: 0x0
 # CHECK:     Type: CodeView (0x2)
@@ -37,7 +37,7 @@
 # CHECK: DebugDirectory [
 # CHECK:   DebugEntry {
 # CHECK:     Characteristics: 0x0
-# CHECK:     TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+# CHECK:     TimeDateStamp: 
 # CHECK:     MajorVersion: 0x0
 # CHECK:     MinorVersion: 0x0
 # CHECK:     Type: CodeView (0x2)
diff --git a/test/COFF/string-tail-merge.s b/test/COFF/string-tail-merge.s
new file mode 100644
index 0000000..f55041f
--- /dev/null
+++ b/test/COFF/string-tail-merge.s
@@ -0,0 +1,87 @@
+# REQUIRES: x86
+# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s
+# RUN: lld-link %t.obj /out:%t.exe /entry:main /subsystem:console
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .rdata:
+# CHECK-NEXT:  140002000 68656c6c 6f20776f 726c6400 6fa26ca4  hello world.o.l.
+# CHECK-NEXT:  140002010 0068656c 6c6f2077 6f726c64 00006865  .hello world..he
+# CHECK-NEXT:  140002020 6c6c6f20 776f726c 64006800 65006c00  llo world.h.e.l.
+# CHECK-NEXT:  140002030 6c006f00 20007700 6f007200 6c006400  l.o. .w.o.r.l.d.
+# CHECK-NEXT:  140002040 0000                                 ..
+
+# CHECK: Contents of section .text:
+.globl main
+main:
+# CHECK-NEXT: 140003000 11200040 01000000 17200040 01000000
+.8byte "??_C@_0M@LACCCNMM@hello?5world?$AA@"
+.8byte "??_C@_05MCBCHHEJ@world?$AA@"
+# CHECK-NEXT: 140003010 2a200040 01000000 36200040 01000000
+.8byte "??_C@_1BI@HHJHKLLN@?$AAh?$AAe?$AAl?$AAl?$AAo?$AA?5?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@"
+.8byte "??_C@_1M@NBBDDHIO@?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@"
+# CHECK-NEXT: 140003020 00200040 01000000 0c200040 01000000
+.8byte "??_D@not_a_string_literal"
+.8byte "??_C@string_literal_with_relocs"
+# CHECK-NEXT: 140003030 00100040 01000000 1e200040 01000000
+.8byte "??_C@string_literal_in_wrong_section"
+.8byte "??_C@overaligned_string_literal"
+
+.section .rdata,"dr",discard,"??_C@_0M@LACCCNMM@hello?5world?$AA@"
+.globl "??_C@_0M@LACCCNMM@hello?5world?$AA@"
+"??_C@_0M@LACCCNMM@hello?5world?$AA@":
+.asciz "hello world"
+
+.section .rdata,"dr",discard,"??_C@_05MCBCHHEJ@world?$AA@"
+.globl "??_C@_05MCBCHHEJ@world?$AA@"
+"??_C@_05MCBCHHEJ@world?$AA@":
+.asciz "world"
+
+.section .rdata,"dr",discard,"??_C@_1BI@HHJHKLLN@?$AAh?$AAe?$AAl?$AAl?$AAo?$AA?5?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@"
+.globl "??_C@_1BI@HHJHKLLN@?$AAh?$AAe?$AAl?$AAl?$AAo?$AA?5?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@"
+.p2align 1
+"??_C@_1BI@HHJHKLLN@?$AAh?$AAe?$AAl?$AAl?$AAo?$AA?5?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@":
+.short 104
+.short 101
+.short 108
+.short 108
+.short 111
+.short 32
+.short 119
+.short 111
+.short 114
+.short 108
+.short 100
+.short 0
+
+.section .rdata,"dr",discard,"??_C@_1M@NBBDDHIO@?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@"
+.globl "??_C@_1M@NBBDDHIO@?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@"
+.p2align 1
+"??_C@_1M@NBBDDHIO@?$AAw?$AAo?$AAr?$AAl?$AAd?$AA?$AA@":
+.short 119
+.short 111
+.short 114
+.short 108
+.short 100
+.short 0
+
+.section .data,"drw",discard,"??_C@string_literal_in_wrong_section"
+.globl "??_C@string_literal_in_wrong_section"
+"??_C@string_literal_in_wrong_section":
+.asciz "hello world"
+
+.section .rdata,"dr",discard,"??_D@not_a_string_literal"
+.globl "??_D@not_a_string_literal"
+"??_D@not_a_string_literal":
+.asciz "hello world"
+
+.section .rdata,"dr",discard,"??_C@string_literal_with_relocs"
+.globl "??_C@string_literal_with_relocs"
+"??_C@string_literal_with_relocs":
+.4byte main + 111 + (114 << 8) + (108 << 16) + (100 << 24) # main + "orld"
+.byte 0
+
+.section .rdata,"dr",discard,"??_C@overaligned_string_literal"
+.globl "??_C@overaligned_string_literal"
+.p2align 1
+"??_C@overaligned_string_literal":
+.asciz "hello world"
diff --git a/test/COFF/weak-external.test b/test/COFF/weak-external.test
index 7bdadd9..141d5ed 100644
--- a/test/COFF/weak-external.test
+++ b/test/COFF/weak-external.test
@@ -5,6 +5,7 @@
 # RUN: FileCheck %s < %t2.map
 
 # CHECK: lto.tmp
+# CHECK-NEXT: lto.tmp
 # CHECK-NEXT: 0 g
 
 --- !COFF
diff --git a/test/COFF/weak-external3.test b/test/COFF/weak-external3.test
index a06ce48..8d2bde2 100644
--- a/test/COFF/weak-external3.test
+++ b/test/COFF/weak-external3.test
@@ -6,6 +6,7 @@
 # RUN: FileCheck --check-prefix=CHECK2 %s < %t2.map
 
 # CHECK1: lto.tmp
+# CHECK1: lto.tmp
 # CHECK1-NEXT: 0 g
 
 # CHECK2: weak-external3.test.tmp.obj
diff --git a/test/ELF/Inputs/arm-long-thunk-converge.lds b/test/ELF/Inputs/arm-long-thunk-converge.lds
new file mode 100644
index 0000000..592d400
--- /dev/null
+++ b/test/ELF/Inputs/arm-long-thunk-converge.lds
@@ -0,0 +1,4 @@
+SECTIONS {
+  .foo : { *(.foo) }
+  .bar 0x2000000 : { *(.bar) }
+}
diff --git a/test/ELF/Inputs/conflict-debug.s b/test/ELF/Inputs/conflict-debug.s
index 03fb013..c38771e 100644
--- a/test/ELF/Inputs/conflict-debug.s
+++ b/test/ELF/Inputs/conflict-debug.s
@@ -3,3 +3,24 @@
 .loc 1 4
 zed:
   nop
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.byte	17                      # DW_TAG_compile_unit
+	.byte	0                       # DW_CHILDREN_no
+	.byte	16                      # DW_AT_stmt_list
+	.byte	23                      # DW_FORM_sec_offset
+	.byte	0                       # EOM(1)
+	.byte	0                       # EOM(2)
+	.byte	0                       # EOM(3)
+
+        .section	.debug_info,"",@progbits
+	.long	.Lend0 - .Lbegin0       # Length of Unit
+.Lbegin0:
+	.short	4                       # DWARF version number
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+	.byte	8                       # Address Size (in bytes)
+	.byte	1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+	.long	.debug_line             # DW_AT_stmt_list
+.Lend0:
+	.section	.debug_line,"",@progbits
diff --git a/test/ELF/Inputs/far-long-arm-abs.s b/test/ELF/Inputs/far-long-arm-abs.s
new file mode 100644
index 0000000..10d9d02
--- /dev/null
+++ b/test/ELF/Inputs/far-long-arm-abs.s
@@ -0,0 +1,13 @@
+.global far
+.type far,%function
+far = 0x201001c
+
+.global too_far1
+.type too_far1,%function
+too_far1 = 0x2020014
+.global too_far2
+.type too_far2,%function
+too_far2 = 0x2020020
+.global too_far3
+.type too_far3,%function
+too_far3 = 0x202002c
diff --git a/test/ELF/Inputs/i386-pic-plt.s b/test/ELF/Inputs/i386-pic-plt.s
new file mode 100644
index 0000000..a7a8121
--- /dev/null
+++ b/test/ELF/Inputs/i386-pic-plt.s
@@ -0,0 +1,4 @@
+        .global foo
+        .type foo, @function
+foo:
+        nop
diff --git a/test/ELF/Inputs/map-file2.s b/test/ELF/Inputs/map-file2.s
index d46b06f..b830bbc 100644
--- a/test/ELF/Inputs/map-file2.s
+++ b/test/ELF/Inputs/map-file2.s
@@ -1,5 +1,7 @@
 foo:
+.cfi_startproc
 nop
+.cfi_endproc
 .global bar
 bar:
 nop
diff --git a/test/ELF/Inputs/multiple-cu.s b/test/ELF/Inputs/multiple-cu.s
new file mode 100644
index 0000000..ff29d36
--- /dev/null
+++ b/test/ELF/Inputs/multiple-cu.s
@@ -0,0 +1,24 @@
+        .file   1 "test2.c"
+        .loc    1 2 0
+        jmp     bar
+
+        .section        .debug_abbrev,"",@progbits
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   0                       # DW_CHILDREN_no
+        .byte   16                      # DW_AT_stmt_list
+        .byte   23                      # DW_FORM_sec_offset
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+
+        .section        .debug_info,"",@progbits
+        .long   .Lend0 - .Lbegin0       # Length of Unit
+.Lbegin0:
+        .short  4                       # DWARF version number
+        .long   .debug_abbrev           # Offset Into Abbrev. Section
+        .byte   8                       # Address Size (in bytes)
+        .byte   1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+        .long   .debug_line             # DW_AT_stmt_list
+.Lend0:
+        .section        .debug_line,"",@progbits
diff --git a/test/ELF/Inputs/undef-bad-debug.s b/test/ELF/Inputs/undef-bad-debug.s
new file mode 100644
index 0000000..c887b28
--- /dev/null
+++ b/test/ELF/Inputs/undef-bad-debug.s
@@ -0,0 +1,44 @@
+.section .text,"ax"
+sym:
+    .quad zed6
+    
+.section .debug_info,"",@progbits
+    .long   .Lcu_end - .Lcu_start   # Length of Unit
+.Lcu_start:
+    .short  4                       # DWARF version number
+    .long   .Lsection_abbrev        # Offset Into Abbrev. Section
+    .byte   8                       # Address Size (in bytes)
+    .byte   1                       # Abbrev [1] 0xb:0x79 DW_TAG_compile_unit
+    .byte   2                       # Abbrev [2] 0x2a:0x15 DW_TAG_variable
+    .long   .Linfo_string           # DW_AT_name
+                                        # DW_AT_external
+    .byte   1                       # DW_AT_decl_file
+    .byte   3                       # DW_AT_decl_line
+    .byte   0                       # End Of Children Mark
+.Lcu_end:
+
+.section .debug_abbrev,"",@progbits
+.Lsection_abbrev:
+    .byte   1                       # Abbreviation Code
+    .byte   17                      # DW_TAG_compile_unit
+    .byte   1                       # DW_CHILDREN_yes
+    .byte   0                       # EOM(1)
+    .byte   0                       # EOM(2)
+    .byte   2                       # Abbreviation Code
+    .byte   52                      # DW_TAG_variable
+    .byte   0                       # DW_CHILDREN_no
+    .byte   3                       # DW_AT_name
+    .byte   14                      # DW_FORM_strp
+    .byte   63                      # DW_AT_external
+    .byte   25                      # DW_FORM_flag_present
+    .byte   58                      # DW_AT_decl_file
+    .byte   11                      # DW_FORM_data1
+    .byte   59                      # DW_AT_decl_line
+    .byte   11                      # DW_FORM_data1
+    .byte   0                       # EOM(1)
+    .byte   0                       # EOM(2)
+    .byte   0                       # EOM(3)
+
+.section .debug_str,"MS",@progbits,1
+.Linfo_string:
+    .asciz "sym"
diff --git a/test/ELF/Inputs/undef-debug.s b/test/ELF/Inputs/undef-debug.s
index db8aaf1..46c1c92 100644
--- a/test/ELF/Inputs/undef-debug.s
+++ b/test/ELF/Inputs/undef-debug.s
@@ -9,3 +9,24 @@
 .section .text.2,"ax"
 .loc 1 11
         .quad zed5
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.byte	17                      # DW_TAG_compile_unit
+	.byte	0                       # DW_CHILDREN_no
+	.byte	16                      # DW_AT_stmt_list
+	.byte	23                      # DW_FORM_sec_offset
+	.byte	0                       # EOM(1)
+	.byte	0                       # EOM(2)
+	.byte	0                       # EOM(3)
+
+        .section	.debug_info,"",@progbits
+	.long	.Lend0 - .Lbegin0       # Length of Unit
+.Lbegin0:
+	.short	4                       # DWARF version number
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+	.byte	8                       # Address Size (in bytes)
+	.byte	1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+	.long	.debug_line             # DW_AT_stmt_list
+.Lend0:
+	.section	.debug_line,"",@progbits
diff --git a/test/ELF/aarch64-fpic-add_abs_lo12_nc.s b/test/ELF/aarch64-fpic-add_abs_lo12_nc.s
index 9e13fd1..9f56081 100644
--- a/test/ELF/aarch64-fpic-add_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-add_abs_lo12_nc.s
@@ -1,7 +1,7 @@
 // REQUIRES: aarch64
 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
 // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: can't create dynamic relocation R_AARCH64_ADD_ABS_LO12_NC against symbol: dat
+// CHECK: can't create dynamic relocation R_AARCH64_ADD_ABS_LO12_NC against symbol: dat in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.o
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
 
diff --git a/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
index 02b75a5..b263fe7 100644
--- a/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
@@ -1,7 +1,7 @@
 // REQUIRES: aarch64
 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
 // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: can't create dynamic relocation R_AARCH64_LDST32_ABS_LO12_NC against symbol: dat
+// CHECK: can't create dynamic relocation R_AARCH64_LDST32_ABS_LO12_NC against symbol: dat in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.o
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
 
diff --git a/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
index 45e4f20..3739ab3 100644
--- a/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
@@ -1,7 +1,7 @@
 // REQUIRES: aarch64
 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
 // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: can't create dynamic relocation R_AARCH64_LDST64_ABS_LO12_NC against symbol: dat
+// CHECK: can't create dynamic relocation R_AARCH64_LDST64_ABS_LO12_NC against symbol: dat in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.o
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
 
diff --git a/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
index 16e7df1..4354ffd 100644
--- a/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
+++ b/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
@@ -1,7 +1,7 @@
 // REQUIRES: aarch64
 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
 // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
-// CHECK: can't create dynamic relocation R_AARCH64_LDST8_ABS_LO12_NC against symbol: dat
+// CHECK: can't create dynamic relocation R_AARCH64_LDST8_ABS_LO12_NC against symbol: dat in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.o
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
 
diff --git a/test/ELF/allow-multiple-definition.s b/test/ELF/allow-multiple-definition.s
index 551c54b..06684f4 100644
--- a/test/ELF/allow-multiple-definition.s
+++ b/test/ELF/allow-multiple-definition.s
@@ -4,13 +4,13 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/allow-multiple-definition.s -o %t2
 # RUN: not ld.lld %t1 %t2 -o %t3
 # RUN: not ld.lld --allow-multiple-definition --no-allow-multiple-definition %t1 %t2 -o %t3
-# RUN: ld.lld --allow-multiple-definition %t1 %t2 -o %t3
-# RUN: ld.lld --allow-multiple-definition %t2 %t1 -o %t4
+# RUN: ld.lld --allow-multiple-definition --fatal-warnings %t1 %t2 -o %t3
+# RUN: ld.lld --allow-multiple-definition --fatal-warnings %t2 %t1 -o %t4
 # RUN: llvm-objdump -d %t3 | FileCheck %s
 # RUN: llvm-objdump -d %t4 | FileCheck -check-prefix=REVERT %s
 
-# RUN: ld.lld -z muldefs %t1 %t2 -o %t3
-# RUN: ld.lld -z muldefs %t2 %t1 -o %t4
+# RUN: ld.lld -z muldefs --fatal-warnings  %t1 %t2 -o %t3
+# RUN: ld.lld -z muldefs --fatal-warnings  %t2 %t1 -o %t4
 # RUN: llvm-objdump -d %t3 | FileCheck %s
 # RUN: llvm-objdump -d %t4 | FileCheck -check-prefix=REVERT %s
 
diff --git a/test/ELF/arm-branch-rangethunk.s b/test/ELF/arm-branch-rangethunk.s
index c61ec89..e541f98 100644
--- a/test/ELF/arm-branch-rangethunk.s
+++ b/test/ELF/arm-branch-rangethunk.s
@@ -1,7 +1,10 @@
 // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
 // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar
 // RUN: ld.lld  %t %tfar -o %t2 2>&1
-// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=SHORT %s
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-long-arm-abs.s -o %tfarlong
+// RUN: ld.lld  %t %tfarlong -o %t3 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck --check-prefix=LONG %s
 // REQUIRES: arm
  .syntax unified
  .section .text, "ax",%progbits
@@ -15,20 +18,32 @@
  b   too_far2
  beq too_far3
 
-// CHECK: Disassembly of section .text:
-// CHECK-NEXT: _start:
-// CHECK-NEXT:    20000:       01 00 00 eb     bl      #4 <__ARMv7ABSLongThunk_too_far1>
-// CHECK-NEXT:    20004:       03 00 00 ea     b       #12 <__ARMv7ABSLongThunk_too_far2>
-// CHECK-NEXT:    20008:       05 00 00 0a     beq     #20 <__ARMv7ABSLongThunk_too_far3>
-// CHECK: __ARMv7ABSLongThunk_too_far1:
-// CHECK-NEXT:    2000c:       08 c0 00 e3     movw    r12, #8
-// CHECK-NEXT:    20010:       02 c2 40 e3     movt    r12, #514
-// CHECK-NEXT:    20014:       1c ff 2f e1     bx      r12
-// CHECK: __ARMv7ABSLongThunk_too_far2:
-// CHECK-NEXT:    20018:       0c c0 00 e3     movw    r12, #12
-// CHECK-NEXT:    2001c:       02 c2 40 e3     movt    r12, #514
-// CHECK-NEXT:    20020:       1c ff 2f e1     bx      r12
-// CHECK: __ARMv7ABSLongThunk_too_far3:
-// CHECK-NEXT:    20024:       10 c0 00 e3     movw    r12, #16
-// CHECK-NEXT:    20028:       02 c2 40 e3     movt    r12, #514
-// CHECK-NEXT:    2002c:       1c ff 2f e1     bx      r12
+// SHORT: Disassembly of section .text:
+// SHORT-NEXT: _start:
+// SHORT-NEXT:    20000:       01 00 00 eb     bl      #4 <__ARMv7ABSLongThunk_too_far1>
+// SHORT-NEXT:    20004:       01 00 00 ea     b       #4 <__ARMv7ABSLongThunk_too_far2>
+// SHORT-NEXT:    20008:       01 00 00 0a     beq     #4 <__ARMv7ABSLongThunk_too_far3>
+// SHORT: __ARMv7ABSLongThunk_too_far1:
+// SHORT-NEXT:    2000c:       fd ff 7f ea     b       #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff4>
+// SHORT: __ARMv7ABSLongThunk_too_far2:
+// SHORT-NEXT:    20010:       fd ff 7f ea     b       #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff8>
+// SHORT: __ARMv7ABSLongThunk_too_far3:
+// SHORT-NEXT:    20014:       fd ff 7f ea     b       #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffffc>
+
+// LONG: Disassembly of section .text:
+// LONG-NEXT: _start:
+// LONG-NEXT:    20000:       01 00 00 eb     bl      #4 <__ARMv7ABSLongThunk_too_far1>
+// LONG-NEXT:    20004:       03 00 00 ea     b       #12 <__ARMv7ABSLongThunk_too_far2>
+// LONG-NEXT:    20008:       05 00 00 0a     beq     #20 <__ARMv7ABSLongThunk_too_far3>
+// LONG: __ARMv7ABSLongThunk_too_far1:
+// LONG-NEXT:    2000c:       14 c0 00 e3     movw    r12, #20
+// LONG-NEXT:    20010:       02 c2 40 e3     movt    r12, #514
+// LONG-NEXT:    20014:       1c ff 2f e1     bx      r12
+// LONG: __ARMv7ABSLongThunk_too_far2:
+// LONG-NEXT:    20018:       20 c0 00 e3     movw    r12, #32
+// LONG-NEXT:    2001c:       02 c2 40 e3     movt    r12, #514
+// LONG-NEXT:    20020:       1c ff 2f e1     bx      r12
+// LONG: __ARMv7ABSLongThunk_too_far3:
+// LONG-NEXT:    20024:       2c c0 00 e3     movw    r12, #44
+// LONG-NEXT:    20028:       02 c2 40 e3     movt    r12, #514
+// LONG-NEXT:    2002c:       1c ff 2f e1     bx      r12
diff --git a/test/ELF/arm-execute-only.s b/test/ELF/arm-execute-only.s
index c88ac29..655a2c6 100644
--- a/test/ELF/arm-execute-only.s
+++ b/test/ELF/arm-execute-only.s
@@ -14,7 +14,7 @@
 // RUN: llvm-readelf -l %t.so | FileCheck --check-prefix=DIFF %s
 
 // CHECK-NOT:  LOAD
-// CHECK:      LOAD           0x000000 0x00000000 0x00000000 0x00169  0x00169  R   0x1000
+// CHECK:      LOAD           0x000000 0x00000000 0x00000000 0x0016d  0x0016d  R   0x1000
 // CHECK:      LOAD           0x001000 0x00001000 0x00001000 0x{{.*}} 0x{{.*}} R E 0x1000
 // CHECK:      LOAD           0x002000 0x00002000 0x00002000 0x{{.*}} 0x{{.*}}   E 0x1000
 // CHECK:      LOAD           0x003000 0x00003000 0x00003000 0x00038  0x00038  RW  0x1000
@@ -26,7 +26,7 @@
 // CHECK: 04     .dynamic
 
 // DIFF-NOT:  LOAD
-// DIFF:      LOAD           0x000000 0x00000000 0x00000000 0x00149 0x00149 R   0x1000
+// DIFF:      LOAD           0x000000 0x00000000 0x00000000 0x0014d 0x0014d R   0x1000
 // DIFF:      LOAD           0x001000 0x00001000 0x00001000 0x0000c 0x0000c R E 0x1000
 // DIFF:      LOAD           0x002000 0x00002000 0x00002000 0x00038 0x00038 RW  0x1000
 // DIFF-NOT:  LOAD
diff --git a/test/ELF/arm-long-thunk-converge.s b/test/ELF/arm-long-thunk-converge.s
new file mode 100644
index 0000000..dadc7e5
--- /dev/null
+++ b/test/ELF/arm-long-thunk-converge.s
@@ -0,0 +1,29 @@
+// REQUIRES: arm
+// RUN: llvm-mc -triple armv7-unknown-gnu -filetype=obj -o %t %s
+// RUN: ld.lld %t %S/Inputs/arm-long-thunk-converge.lds -o %t2
+// RUN: llvm-objdump -d -start-address=0x00000000 -stop-address=0x00000010 -triple=armv7a-linux-gnueabihf %t2 | FileCheck --check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d -start-address=0x02000000 -stop-address=0x02000010 -triple=armv7a-linux-gnueabihf %t2 | FileCheck --check-prefix=CHECK2 %s
+// RUN: rm -f %t2
+
+// CHECK1: __ARMv7ABSLongThunk_bar:
+// CHECK1-NEXT:        0:       0c c0 00 e3     movw    r12, #12
+// CHECK1-NEXT:        4:       00 c2 40 e3     movt    r12, #512
+// CHECK1-NEXT:        8:       1c ff 2f e1     bx      r12
+// CHECK1: foo:
+// CHECK1-NEXT:        c:       fb ff ff eb     bl      #-20
+
+.section .foo,"ax",%progbits,unique,1
+foo:
+bl bar
+
+// CHECK2: __ARMv7ABSLongThunk_foo:
+// CHECK2-NEXT:  2000000:       0c c0 00 e3     movw    r12, #12
+// CHECK2-NEXT:  2000004:       00 c0 40 e3     movt    r12, #0
+// CHECK2-NEXT:  2000008:       1c ff 2f e1     bx      r12
+// CHECK2: bar:
+// CHECK2-NEXT:  200000c:       fb ff ff eb     bl      #-20 <__ARMv7ABSLongThunk_foo>
+
+.section .bar,"ax",%progbits,unique,1
+bar:
+bl foo
+.zero 0x1000000
diff --git a/test/ELF/arm-target1.s b/test/ELF/arm-target1.s
index e77fa57..2fc0b8b 100644
--- a/test/ELF/arm-target1.s
+++ b/test/ELF/arm-target1.s
@@ -31,6 +31,6 @@
 // RELATIVE: SYMBOL TABLE:
 // RELATIVE: 00001004         .text           00000000 patatino
 
-// ABS: can't create dynamic relocation R_ARM_TARGET1 against symbol: patatino
+// ABS: can't create dynamic relocation R_ARM_TARGET1 against symbol: patatino in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // ABS: >>> defined in {{.*}}.o
 // ABS: >>> referenced by {{.*}}.o:(.text+0x0)
diff --git a/test/ELF/arm-thumb-condbranch-thunk.s b/test/ELF/arm-thumb-condbranch-thunk.s
index c527e5d..c9365ef 100644
--- a/test/ELF/arm-thumb-condbranch-thunk.s
+++ b/test/ELF/arm-thumb-condbranch-thunk.s
@@ -38,13 +38,9 @@
 // CHECK1-NEXT:    80000:       70 47   bx      lr
 // CHECK1-NEXT:    80002:       7f f3 ff d7     bl      #16252926
 // CHECK1: __Thumbv7ABSLongThunk_tfunc05:
-// CHECK1-NEXT:    80008:       40 f2 01 0c     movw    r12, #1
-// CHECK1-NEXT:    8000c:       c0 f2 30 0c     movt    r12, #48
-// CHECK1-NEXT:    80010:       60 47   bx      r12
+// CHECK1-NEXT:    80008:       7f f2 fa bf     b.w     #2621428 <tfunc05>
 // CHECK1: __Thumbv7ABSLongThunk_tfunc00:
-// CHECK1-NEXT:    80012:       40 f2 01 0c     movw    r12, #1
-// CHECK1-NEXT:    80016:       c0 f2 08 0c     movt    r12, #8
-// CHECK1-NEXT:    8001a:       60 47   bx      r12
+// CHECK1-NEXT:    8000c:       ff f7 f8 bf     b.w     #-16 <tfunc00>
  FUNCTION 01
 // tfunc02 is within range of tfunc02
  beq.w tfunc02
@@ -61,7 +57,7 @@
  beq.w tfunc00
 // CHECK3:   180000:       70 47   bx      lr
 // CHECK3-NEXT:   180002:       40 f4 01 80     bne.w   #-1048574 <__Thumbv7ABSLongThunk_tfunc05>
-// CHECK3-NEXT:   180006:       00 f4 04 80     beq.w   #-1048568 <__Thumbv7ABSLongThunk_tfunc00>
+// CHECK3-NEXT:   180006:       00 f4 01 80     beq.w   #-1048574 <__Thumbv7ABSLongThunk_tfunc00>
  FUNCTION 03
  FUNCTION 04
  FUNCTION 05
@@ -70,9 +66,7 @@
  FUNCTION 08
  FUNCTION 09
 // CHECK4:  __Thumbv7ABSLongThunk_tfunc03:
-// CHECK4-NEXT:   500004:       40 f2 01 0c     movw    r12, #1
-// CHECK4-NEXT:   500008:       c0 f2 20 0c     movt    r12, #32
-// CHECK4-NEXT:   50000c:       60 47   bx      r12
+// CHECK4-NEXT:   500004:       ff f4 fc bf     b.w     #-3145736 <tfunc03>
  FUNCTION 10
 // We can't reach any Thunk Section, create a new one
  beq.w tfunc03
@@ -101,17 +95,13 @@
  FUNCTION 30
  FUNCTION 31
 // CHECK6:  __Thumbv7ABSLongThunk_tfunc33:
-// CHECK6-NEXT:  1000004:       40 f2 01 0c     movw    r12, #1
-// CHECK6-NEXT:  1000008:       c0 f2 10 1c     movt    r12, #272
-// CHECK6-NEXT:  100000c:       60 47   bx      r12
+// CHECK6-NEXT:  1000004:       ff f0 fc bf     b.w     #1048568 <tfunc33>
 // CHECK6: __Thumbv7ABSLongThunk_tfunc00:
-// CHECK6-NEXT:  100000e:       40 f2 01 0c     movw    r12, #1
-// CHECK6-NEXT:  1000012:       c0 f2 08 0c     movt    r12, #8
-// CHECK6-NEXT:  1000016:       60 47   bx      r12
+// CHECK6-NEXT:  1000008:       7f f4 fa 97     b.w     #-16252940 <tfunc00>
  FUNCTION 32
  FUNCTION 33
  // We should be able to reach an existing ThunkSection.
  b.w tfunc00
 // CHECK7: tfunc33:
 // CHECK7-NEXT:  1100000:       70 47   bx      lr
-// CHECK7-NEXT:  1100002:       00 f7 04 b8     b.w     #-1048568 <__Thumbv7ABSLongThunk_tfunc00>
+// CHECK7-NEXT:  1100002:       00 f7 01 b8     b.w     #-1048574 <__Thumbv7ABSLongThunk_tfunc00>
diff --git a/test/ELF/arm-thumb-mix-range-thunk-os.s b/test/ELF/arm-thumb-mix-range-thunk-os.s
index beff414..b5db256 100644
--- a/test/ELF/arm-thumb-mix-range-thunk-os.s
+++ b/test/ELF/arm-thumb-mix-range-thunk-os.s
@@ -11,7 +11,7 @@
 // RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651590 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s
 // RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700168 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s
 // RUN: llvm-objdump -d %t2 -start-address=48234500 -stop-address=48234512 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s
-// RUN: llvm-objdump -d %t2 -start-address=63963140 -stop-address=63963160 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s
+// RUN: llvm-objdump -d %t2 -start-address=53477380 -stop-address=53477392 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s
 // RUN: llvm-objdump -d %t2 -start-address=68157440 -stop-address=68157452 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s
 // RUN: llvm-objdump -d %t2 -start-address=69206016 -stop-address=69206024 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK11 %s
 
@@ -155,6 +155,13 @@
  ARMFUNCTION 48
  THUMBFUNCTION 49
  ARMFUNCTION 50
+// Expect precreated Thunk Section here
+// CHECK9: __Thumbv7ABSLongThunk_afunc34:
+// CHECK9-NEXT:  3300004:       40 f2 00 0c     movw    r12, #0
+// CHECK9-NEXT:  3300008:       c0 f2 30 2c     movt    r12, #560
+// CHECK9-NEXT:  330000c:       60 47   bx      r12
+// CHECK9: __Thumbv7ABSLongThunk_tfunc35:
+// CHECK9-NEXT:  330000e:       ff f4 f7 97     b.w     #-15728658 <tfunc35>
  THUMBFUNCTION 51
  ARMFUNCTION 52
  THUMBFUNCTION 53
@@ -165,15 +172,6 @@
  ARMFUNCTION 58
  THUMBFUNCTION 59
  ARMFUNCTION 60
-// Expect precreated Thunk Section here
-// CHECK9: __Thumbv7ABSLongThunk_afunc34:
-// CHECK9-NEXT:  3d00004:       40 f2 00 0c     movw    r12, #0
-// CHECK9-NEXT:  3d00008:       c0 f2 30 2c     movt    r12, #560
-// CHECK9-NEXT:  3d0000c:       60 47   bx      r12
-// CHECK9: __Thumbv7ABSLongThunk_tfunc35:
-// CHECK9-NEXT:  3d0000e:       40 f2 01 0c     movw    r12, #1
-// CHECK9-NEXT:  3d00012:       c0 f2 40 2c     movt    r12, #576
-// CHECK9-NEXT:  3d00016:       60 47   bx      r12
  THUMBFUNCTION 61
  ARMFUNCTION 62
  THUMBFUNCTION 63
@@ -191,5 +189,5 @@
  bl tfunc35
 // CHECK11: tfunc65:
 // CHECK11:  4200000:   70 47   bx      lr
-// CHECK11-NEXT:  4200002:      ff f6 ff f7     bl      #-5242882
-// CHECK11-NEXT:  4200006:      00 f7 02 f0     bl      #-5242876
+// CHECK11-NEXT:  4200002:      ff f4 ff d7     bl      #-15728642
+// CHECK11-NEXT:  4200006:      00 f5 02 d0     bl      #-15728636
diff --git a/test/ELF/arm-thumb-plt-range-thunk-os.s b/test/ELF/arm-thumb-plt-range-thunk-os.s
index f412faa..080160b 100644
--- a/test/ELF/arm-thumb-plt-range-thunk-os.s
+++ b/test/ELF/arm-thumb-plt-range-thunk-os.s
@@ -1,12 +1,12 @@
 // REQUIRES: arm
 // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
-// RUN: ld.lld %t --shared -o %t.so
+// RUN: ld.lld %t --shared --icf=all -o %t.so
 // The output file is large, most of it zeroes. We dissassemble only the
 // parts we need to speed up the test and avoid a large output file
-// RUN: llvm-objdump -d %t.so -start-address=8388608 -stop-address=8388624 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
-// RUN: llvm-objdump -d %t.so -start-address=16777216 -stop-address=16777256 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
-// RUN: llvm-objdump -d %t.so -start-address=25165824 -stop-address=25165828 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
-// RUN: llvm-objdump -d %t.so -start-address=25165828 -stop-address=25165924 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
+// RUN: llvm-objdump -d %t.so -start-address=0x2000000 -stop-address=0x2000018 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d %t.so -start-address=0x2800004 -stop-address=0x2800034 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t.so -start-address=0x4000000 -stop-address=0x4000010 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d %t.so -start-address=0x4000010 -stop-address=0x4000100 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
  .syntax unified
  .thumb
 
@@ -19,74 +19,96 @@
  .type preemptible, %function
  .global far_preemptible
  .type far_preemptible, %function
+ .global far_nonpreemptible
+ .hidden far_nonpreemptible
+ .type far_nonpreemptible, %function
+ .global far_nonpreemptible_alias
+ .hidden far_nonpreemptible_alias
+ .type far_nonpreemptible_alias, %function
 sym1:
  bl elsewhere
  bl preemptible
  bx lr
 preemptible:
  bl far_preemptible
+ bl far_nonpreemptible
+ bl far_nonpreemptible_alias
  bx lr
 // CHECK1: Disassembly of section .text:
 // CHECK1-NEXT: sym1:
-// CHECK1-NEXT:   800000:       00 f0 00 d8     bl      #8388608
-// CHECK1-NEXT:   800004:       00 f0 04 d8     bl      #8388616
-// CHECK1-NEXT:   800008:       70 47   bx      lr
+// CHECK1-NEXT:  2000000:       00 f0 00 d8     bl      #8388608
+// CHECK1-NEXT:  2000004:       00 f0 04 d8     bl      #8388616
+// CHECK1-NEXT:  2000008:       70 47   bx      lr
 // CHECK1: preemptible:
-// CHECK1-NEXT:   80000a:       00 f0 07 d8     bl      #8388622
-// CHECK1-NEXT:   80000e:       70 47   bx      lr
+// CHECK1-NEXT:  200000a:       00 f0 07 d8     bl      #8388622
+// CHECK1-NEXT:  200000e:       00 f0 0b d8     bl      #8388630
+// CHECK1-NEXT:  2000012:       00 f0 09 d8     bl      #8388626
+// CHECK1-NEXT:  2000016:       70 47   bx      lr
 
  .section .text.2, "ax", %progbits
  .balign 0x0800000
  bx lr
 // CHECK2: __ThumbV7PILongThunk_elsewhere:
-// CHECK2-NEXT:  1000004:       40 f2 20 0c     movw    r12, #32
-// CHECK2-NEXT:  1000008:       c0 f2 80 0c     movt    r12, #128
-// CHECK2-NEXT:  100000c:       fc 44   add     r12, pc
-// CHECK2-NEXT:  100000e:       60 47   bx      r12
+// CHECK2-NEXT:  2800004:       40 f2 20 0c     movw    r12, #32
+// CHECK2-NEXT:  2800008:       c0 f2 80 1c     movt    r12, #384
+// CHECK2-NEXT:  280000c:       fc 44   add     r12, pc
+// CHECK2-NEXT:  280000e:       60 47   bx      r12
 // CHECK2: __ThumbV7PILongThunk_preemptible:
-// CHECK2-NEXT:  1000010:       40 f2 24 0c     movw    r12, #36
-// CHECK2-NEXT:  1000014:       c0 f2 80 0c     movt    r12, #128
-// CHECK2-NEXT:  1000018:       fc 44   add     r12, pc
-// CHECK2-NEXT:  100001a:       60 47   bx      r12
+// CHECK2-NEXT:  2800010:       40 f2 24 0c     movw    r12, #36
+// CHECK2-NEXT:  2800014:       c0 f2 80 1c     movt    r12, #384
+// CHECK2-NEXT:  2800018:       fc 44   add     r12, pc
+// CHECK2-NEXT:  280001a:       60 47   bx      r12
 // CHECK2: __ThumbV7PILongThunk_far_preemptible:
-// CHECK2-NEXT:  100001c:       40 f2 28 0c     movw    r12, #40
-// CHECK2-NEXT:  1000020:       c0 f2 80 0c     movt    r12, #128
-// CHECK2-NEXT:  1000024:       fc 44   add     r12, pc
-// CHECK2-NEXT:  1000026:       60 47   bx      r12
+// CHECK2-NEXT:  280001c:       40 f2 28 0c     movw    r12, #40
+// CHECK2-NEXT:  2800020:       c0 f2 80 1c     movt    r12, #384
+// CHECK2-NEXT:  2800024:       fc 44   add     r12, pc
+// CHECK2-NEXT:  2800026:       60 47   bx      r12
+// CHECK2: __ThumbV7PILongThunk_far_nonpreemptible:
+// CHECK2-NEXT:  2800028:       4f f6 cd 7c     movw    r12, #65485
+// CHECK2-NEXT:  280002c:       c0 f2 7f 1c     movt    r12, #383
+// CHECK2-NEXT:  2800030:       fc 44   add     r12, pc
+// CHECK2-NEXT:  2800032:       60 47   bx      r12
 
  .section .text.3, "ax", %progbits
-.balign 0x0800000
+.balign 0x2000000
 far_preemptible:
+far_nonpreemptible:
  bl elsewhere
+
+ .section .text.4, "ax", %progbits
+.balign 0x2000000
+far_nonpreemptible_alias:
+ bl elsewhere
+
 // CHECK3: far_preemptible:
-// CHECK3:  1800000:       00 f0 16 e8     blx     #44
+// CHECK3:  4000000:       00 f0 16 e8     blx     #44
 
 // CHECK4: Disassembly of section .plt:
 // CHECK4-NEXT: $a:
-// CHECK4-NEXT:  1800010:	04 e0 2d e5 	str	lr, [sp, #-4]!
-// CHECK4-NEXT:  1800014:	00 e6 8f e2 	add	lr, pc, #0, #12
-// CHECK4-NEXT:  1800018:	00 ea 8e e2 	add	lr, lr, #0, #20
-// CHECK4-NEXT:  180001c:	ec ff be e5 	ldr	pc, [lr, #4076]!
+// CHECK4-NEXT:  4000010:	04 e0 2d e5 	str	lr, [sp, #-4]!
+// CHECK4-NEXT:  4000014:	00 e6 8f e2 	add	lr, pc, #0, #12
+// CHECK4-NEXT:  4000018:	00 ea 8e e2 	add	lr, lr, #0, #20
+// CHECK4-NEXT:  400001c:	ec ff be e5 	ldr	pc, [lr, #4076]!
 // CHECK4: $d:
-// CHECK4-NEXT:  1800020:	d4 d4 d4 d4 	.word	0xd4d4d4d4
-// CHECK4-NEXT:  1800024:	d4 d4 d4 d4 	.word	0xd4d4d4d4
-// CHECK4-NEXT:  1800028:	d4 d4 d4 d4 	.word	0xd4d4d4d4
-// CHECK4-NEXT:  180002c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
+// CHECK4-NEXT:  4000020:	d4 d4 d4 d4 	.word	0xd4d4d4d4
+// CHECK4-NEXT:  4000024:	d4 d4 d4 d4 	.word	0xd4d4d4d4
+// CHECK4-NEXT:  4000028:	d4 d4 d4 d4 	.word	0xd4d4d4d4
+// CHECK4-NEXT:  400002c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
 // CHECK4: $a:
-// CHECK4-NEXT:  1800030:	00 c6 8f e2 	add	r12, pc, #0, #12
-// CHECK4-NEXT:  1800034:	00 ca 8c e2 	add	r12, r12, #0, #20
-// CHECK4-NEXT:  1800038:	d4 ff bc e5 	ldr	pc, [r12, #4052]!
+// CHECK4-NEXT:  4000030:	00 c6 8f e2 	add	r12, pc, #0, #12
+// CHECK4-NEXT:  4000034:	00 ca 8c e2 	add	r12, r12, #0, #20
+// CHECK4-NEXT:  4000038:	d4 ff bc e5 	ldr	pc, [r12, #4052]!
 // CHECK4: $d:
-// CHECK4-NEXT:  180003c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
+// CHECK4-NEXT:  400003c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
 // CHECK4: $a:
-// CHECK4-NEXT:  1800040:	00 c6 8f e2 	add	r12, pc, #0, #12
-// CHECK4-NEXT:  1800044:	00 ca 8c e2 	add	r12, r12, #0, #20
-// CHECK4-NEXT:  1800048:	c8 ff bc e5 	ldr	pc, [r12, #4040]!
+// CHECK4-NEXT:  4000040:	00 c6 8f e2 	add	r12, pc, #0, #12
+// CHECK4-NEXT:  4000044:	00 ca 8c e2 	add	r12, r12, #0, #20
+// CHECK4-NEXT:  4000048:	c8 ff bc e5 	ldr	pc, [r12, #4040]!
 // CHECK4: $d:
-// CHECK4-NEXT:  180004c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
+// CHECK4-NEXT:  400004c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
 // CHECK4: $a:
-// CHECK4-NEXT:  1800050:	00 c6 8f e2 	add	r12, pc, #0, #12
-// CHECK4-NEXT:  1800054:	00 ca 8c e2 	add	r12, r12, #0, #20
-// CHECK4-NEXT:  1800058:	bc ff bc e5 	ldr	pc, [r12, #4028]!
+// CHECK4-NEXT:  4000050:	00 c6 8f e2 	add	r12, pc, #0, #12
+// CHECK4-NEXT:  4000054:	00 ca 8c e2 	add	r12, r12, #0, #20
+// CHECK4-NEXT:  4000058:	bc ff bc e5 	ldr	pc, [r12, #4028]!
 // CHECK4: $d:
-// CHECK4-NEXT:  180005c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
+// CHECK4-NEXT:  400005c:	d4 d4 d4 d4 	.word	0xd4d4d4d4
diff --git a/test/ELF/arm-thumb-range-thunk-os.s b/test/ELF/arm-thumb-range-thunk-os.s
index 588539d..182b18d 100644
--- a/test/ELF/arm-thumb-range-thunk-os.s
+++ b/test/ELF/arm-thumb-range-thunk-os.s
@@ -9,8 +9,8 @@
 // RUN: llvm-objdump -d %t2 -start-address=4194304 -stop-address=4194310 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
 // RUN: llvm-objdump -d %t2 -start-address=16777216 -stop-address=16777270 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s
 // RUN: llvm-objdump -d %t2 -start-address=17825792 -stop-address=17825808 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s
-// RUN: llvm-objdump -d %t2 -start-address=31457280 -stop-address=31457286 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s
-// RUN: llvm-objdump -d %t2 -start-address=32505860 -stop-address=32505880 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s
+// RUN: llvm-objdump -d %t2 -start-address=20971524 -stop-address=20971532 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s
+// RUN: llvm-objdump -d %t2 -start-address=31457280 -stop-address=31457286 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s
 // RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651594 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s
 // RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700170 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s
 
@@ -60,7 +60,7 @@
         b.w tfunc28
 // CHECK4: tfunc02:
 // CHECK4-NEXT:   400000:       70 47   bx      lr
-// CHECK4-NEXT:   400002:       00 f0 04 90     b.w     #12582920 <__Thumbv7ABSLongThunk_tfunc28>
+// CHECK4-NEXT:   400002:       00 f0 01 90     b.w     #12582914 <__Thumbv7ABSLongThunk_tfunc28>
  FUNCTION 03
  FUNCTION 04
  FUNCTION 05
@@ -75,25 +75,19 @@
  FUNCTION 14
 // Expect precreated ThunkSection here
 // CHECK5: __Thumbv7ABSLongThunk_tfunc16:
-// CHECK5-NEXT:  1000004:       40 f2 01 0c     movw    r12, #1
-// CHECK5-NEXT:  1000008:       c0 f2 20 1c     movt    r12, #288
-// CHECK5-NEXT:  100000c:       60 47   bx      r12
+// CHECK5-NEXT:  1000004:       ff f1 fc bf     b.w     #2097144 <tfunc16>
 // CHECK5: __Thumbv7ABSLongThunk_tfunc28:
-// CHECK5-NEXT:  100000e:       40 f2 01 0c     movw    r12, #1
-// CHECK5-NEXT:  1000012:       c0 f2 e0 1c     movt    r12, #480
-// CHECK5-NEXT:  1000016:       60 47   bx      r12
+// CHECK5-NEXT:  1000008:       ff f1 fa 97     b.w     #14680052 <tfunc28>
 // CHECK5: __Thumbv7ABSLongThunk_tfunc32:
-// CHECK5-NEXT:  1000018:       40 f2 01 0c     movw    r12, #1
-// CHECK5-NEXT:  100001c:       c0 f2 20 2c     movt    r12, #544
-// CHECK5-NEXT:  1000020:       60 47   bx      r12
+// CHECK5-NEXT:  100000c:       40 f2 01 0c     movw    r12, #1
+// CHECK5-NEXT:  1000010:       c0 f2 20 2c     movt    r12, #544
+// CHECK5-NEXT:  1000014:       60 47   bx      r12
 // CHECK5: __Thumbv7ABSLongThunk_tfunc33:
-// CHECK5-NEXT:  1000022:       40 f2 01 0c     movw    r12, #1
-// CHECK5-NEXT:  1000026:       c0 f2 30 2c     movt    r12, #560
-// CHECK5-NEXT:  100002a:       60 47   bx      r12
+// CHECK5-NEXT:  1000016:       40 f2 01 0c     movw    r12, #1
+// CHECK5-NEXT:  100001a:       c0 f2 30 2c     movt    r12, #560
+// CHECK5-NEXT:  100001e:       60 47   bx      r12
 // CHECK5: __Thumbv7ABSLongThunk_tfunc02:
-// CHECK5-NEXT:  100002c:       40 f2 01 0c     movw    r12, #1
-// CHECK5-NEXT:  1000030:       c0 f2 40 0c     movt    r12, #64
-// CHECK5-NEXT:  1000034:       60 47   bx      r12
+// CHECK5-NEXT:  1000020:       ff f7 ee 97     b.w     #-12582948 <tfunc02>
  FUNCTION 15
 // tfunc00 and tfunc01 are < 16Mb away, expect no range extension thunks
  bl tfunc00
@@ -106,11 +100,16 @@
 // CHECK6-NEXT:  1100000:       70 47   bx      lr
 // CHECK6-NEXT:  1100002:       ff f4 fd d7     bl      #-15728646
 // CHECK6-NEXT:  1100006:       ff f5 fb d7     bl      #-14680074
-// CHECK6-NEXT:  110000a:       00 f7 05 f8     bl      #-1048566
-// CHECK6-NEXT:  110000e:       00 f7 08 f8     bl      #-1048560
+// CHECK6-NEXT:  110000a:       ff f6 ff ff     bl      #-1048578
+// CHECK6-NEXT:  110000e:       00 f7 02 f8     bl      #-1048572
  FUNCTION 16
  FUNCTION 17
  FUNCTION 18
+// Expect another precreated thunk section here
+// CHECK7: __Thumbv7ABSLongThunk_tfunc15:
+// CHECK7-NEXT:  1400004:       ff f4 fc bf     b.w     #-3145736 <tfunc15>
+// CHECK7: __Thumbv7ABSLongThunk_tfunc16:
+// CHECK7-NEXT:  1400008:       ff f5 fa bf     b.w     #-2097164 <tfunc16>
  FUNCTION 19
  FUNCTION 20
  FUNCTION 21
@@ -123,21 +122,12 @@
  FUNCTION 28
 // tfunc02 is > 16Mb away, expect range extension thunks in precreated thunk
 // section
-// CHECK7:  tfunc28:
-// CHECK7-NEXT:  1e00000:       70 47   bx      lr
-// CHECK7-NEXT:  1e00002:       00 f6 13 90     b.w     #-14680026 <__Thumbv7ABSLongThunk_tfunc02>
+// CHECK8:  tfunc28:
+// CHECK8-NEXT:  1e00000:       70 47   bx      lr
+// CHECK8-NEXT:  1e00002:       00 f6 0d 90     b.w     #-14680038 <__Thumbv7ABSLongThunk_tfunc02>
 
  b.w tfunc02
  FUNCTION 29
-// Expect another precreated thunk section here
-// CHECK8: __Thumbv7ABSLongThunk_tfunc15:
-// CHECK8-NEXT:  1f00004:       40 f2 01 0c     movw    r12, #1
-// CHECK8-NEXT:  1f00008:       c0 f2 10 1c     movt    r12, #272
-// CHECK8-NEXT:  1f0000c:       60 47   bx      r12
-// CHECK8: __Thumbv7ABSLongThunk_tfunc16:
-// CHECK8-NEXT:  1f0000e:       40 f2 01 0c     movw    r12, #1
-// CHECK8-NEXT:  1f00012:       c0 f2 20 1c     movt    r12, #288
-// CHECK8-NEXT:  1f00016:       60 47   bx      r12
  FUNCTION 30
  FUNCTION 31
  FUNCTION 32
@@ -147,13 +137,13 @@
  bl tfunc16
 // CHECK9: tfunc32:
 // CHECK9:  2200000:    70 47   bx      lr
-// CHECK9-NEXT:  2200002:       ff f4 ff ff     bl      #-3145730
-// CHECK9-NEXT:  2200006:       00 f5 02 f8     bl      #-3145724
+// CHECK9-NEXT:  2200002:       ff f5 ff d7     bl      #-14680066
+// CHECK9-NEXT:  2200006:       ff f5 ff d7     bl      #-14680066
 
  FUNCTION 33
  bl tfunc15
  bl tfunc16
 // CHECK10: tfunc33:
 // CHECK10:  2300000:   70 47   bx      lr
-// CHECK10-NEXT:  2300002:      ff f7 ff f7     bl      #-4194306
-// CHECK10-NEXT:  2300006:      00 f4 02 f8     bl      #-4194300
+// CHECK10-NEXT:  2300002:      ff f4 ff d7     bl      #-15728642
+// CHECK10-NEXT:  2300006:      ff f4 ff d7     bl      #-15728642
diff --git a/test/ELF/arm-thumb-thunk-empty-pass.s b/test/ELF/arm-thumb-thunk-empty-pass.s
index 9ff6ed6..ab9da1b 100644
--- a/test/ELF/arm-thumb-thunk-empty-pass.s
+++ b/test/ELF/arm-thumb-thunk-empty-pass.s
@@ -2,7 +2,7 @@
 // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t -o %t2 2>&1
 // RUN: llvm-objdump -d %t2 -start-address=69632 -stop-address=69646 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
-// RUN: llvm-objdump -d %t2 -start-address=16846860 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t2 -start-address=16846856 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
  .syntax unified
  .global _start, foo
  .type _start, %function
@@ -20,13 +20,11 @@
 // CHECK1-NEXT: _start:
 // CHECK1-NEXT:    11000:       ff f7 fe ff     bl      #-4
 // CHECK1: __Thumbv7ABSLongThunk__start:
-// CHECK1-NEXT:    11004:       41 f2 01 0c     movw    r12, #4097
-// CHECK1-NEXT:    11008:       c0 f2 01 0c     movt    r12, #1
-// CHECK1-NEXT:    1100c:       60 47   bx      r12
+// CHECK1-NEXT:    11004:       ff f7 fc bf     b.w     #-8 <_start>
 
 // CHECK2: __Thumbv7ABSLongThunk__start:
-// CHECK2:       101100c:       41 f2 01 0c     movw    r12, #4097
-// CHECK2-NEXT:  1011010:       c0 f2 01 0c     movt    r12, #1
-// CHECK2-NEXT:  1011014:       60 47   bx      r12
+// CHECK2:       1011008:       41 f2 01 0c     movw    r12, #4097
+// CHECK2-NEXT:  101100c:       c0 f2 01 0c     movt    r12, #1
+// CHECK2-NEXT:  1011010:       60 47   bx      r12
 // CHECK2: foo:
-// CHECK2-NEXT:  1011016:       ff f7 f9 ff     bl      #-14
+// CHECK2-NEXT:  1011012:       ff f7 f9 ff     bl      #-14
diff --git a/test/ELF/arm-thunk-largesection.s b/test/ELF/arm-thunk-largesection.s
index 950f789..5e882a9 100644
--- a/test/ELF/arm-thunk-largesection.s
+++ b/test/ELF/arm-thunk-largesection.s
@@ -2,9 +2,9 @@
 // RUN: ld.lld %t -o %t2 2>&1
 // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=69632 -stop-address=69636 %t2 | FileCheck -check-prefix=CHECK1 %s
 // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=73732 -stop-address=73742 %t2 | FileCheck -check-prefix=CHECK2 %s
-// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=16850944 -stop-address=16850948 %t2 | FileCheck -check-prefix=CHECK3 %s
-// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=33628160 -stop-address=33628164 %t2 | FileCheck -check-prefix=CHECK4 %s
-// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=50405364 -stop-address=50405376 %t2 | FileCheck -check-prefix=CHECK5 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=16850936 -stop-address=16850940 %t2 | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=33628152 -stop-address=33628156 %t2 | FileCheck -check-prefix=CHECK4 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=50405356 -stop-address=50405376 %t2 | FileCheck -check-prefix=CHECK5 %s
 // REQUIRES: arm
  .syntax unified
  .balign 0x1000
@@ -21,9 +21,7 @@
 // CHECK1-NEXT:    11002:       00 00   movs    r0, r0
 
 // CHECK2: __Thumbv7ABSLongThunk__start:
-// CHECK2-NEXT:    12004:       41 f2 01 0c     movw    r12, #4097
-// CHECK2-NEXT:    12008:       c0 f2 01 0c     movt    r12, #1
-// CHECK2-NEXT:    1200c:       60 47   bx      r12
+// CHECK2-NEXT:    12004:       fe f7 fc bf     b.w     #-4104 <_start>
 
 // Gigantic section where we need a ThunkSection either side of it
  .section .text.large1, "ax", %progbits
@@ -33,10 +31,10 @@
  .space (16 * 1024 * 1024) - 4
  bl _start
  .space (16 * 1024 * 1024) - 16
-// CHECK3: 1012000:     00 f4 00 d0     bl      #-16777216
-// CHECK4: 2012000:     ff f3 f8 d7     bl      #16777200
+// CHECK3: 1011ff8:     00 f4 04 d0     bl      #-16777208
+// CHECK4: 2011ff8:     ff f3 f8 d7     bl      #16777200
 
 // CHECK5: __Thumbv7ABSLongThunk__start:
-// CHECK5-NEXT:  3011ff4:       41 f2 01 0c     movw    r12, #4097
-// CHECK5-NEXT:  3011ff8:       c0 f2 01 0c     movt    r12, #1
-// CHECK5-NEXT:  3011ffc:       60 47   bx      r12
+// CHECK5-NEXT:  3011fec:       41 f2 01 0c     movw    r12, #4097
+// CHECK5-NEXT:  3011ff0:       c0 f2 01 0c     movt    r12, #1
+// CHECK5-NEXT:  3011ff4:       60 47   bx      r12
diff --git a/test/ELF/arm-thunk-linkerscript-large.s b/test/ELF/arm-thunk-linkerscript-large.s
index 07cd1dd..839d771 100644
--- a/test/ELF/arm-thunk-linkerscript-large.s
+++ b/test/ELF/arm-thunk-linkerscript-large.s
@@ -79,9 +79,7 @@
  FUNCTIONL 08
  FUNCTIONL 09
 // CHECK3: __Thumbv7ABSLongThunk_tfuncl24:
-// CHECK3-NEXT:   b00004:	40 f2 01 0c 	movw	r12, #1
-// CHECK3-NEXT:   b00008:	c0 f2 a0 1c 	movt	r12, #416
-// CHECK3-NEXT:   b0000c:	60 47 	bx	r12
+// CHECK3-NEXT:   b00004:      ff f2 fc 97     b.w     #15728632 <tfuncl24>
  FUNCTIONL 10
  FUNCTIONL 11
  FUNCTIONL 12
diff --git a/test/ELF/arm-thunk-linkerscript-sort.s b/test/ELF/arm-thunk-linkerscript-sort.s
index 69d1767..62ea413 100644
--- a/test/ELF/arm-thunk-linkerscript-sort.s
+++ b/test/ELF/arm-thunk-linkerscript-sort.s
@@ -41,9 +41,7 @@
  FUNCTION 16
  FUNCTION 15
 // CHECK2: __Thumbv7ABSLongThunk_tfunc31:
-// CHECK2-NEXT:  1000004:       40 f2 01 0c     movw    r12, #1
-// CHECK2-NEXT:  1000008:       c0 f2 00 2c     movt    r12, #512
-// CHECK2-NEXT:  100000c:       60 47   bx      r12
+// CHECK2-NEXT:  1000004:       ff f3 fc 97     b.w     #16777208 <tfunc31>
  FUNCTION 14
  FUNCTION 13
  FUNCTION 12
diff --git a/test/ELF/arm-thunk-multipass.s b/test/ELF/arm-thunk-multipass.s
index 25bf523..b353bb1 100644
--- a/test/ELF/arm-thunk-multipass.s
+++ b/test/ELF/arm-thunk-multipass.s
@@ -5,7 +5,7 @@
 // parts we need to speed up the test and avoid a large output file
 // RUN: llvm-objdump -d %t2 -start-address=1048578 -stop-address=1048586 -triple=thumbv7a-linux-gnueabihf  | FileCheck -check-prefix=CHECK1 %s
 // RUN: llvm-objdump -d %t2 -start-address=16777224 -stop-address=16777254 -triple=thumbv7a-linux-gnueabihf  | FileCheck -check-prefix=CHECK2 %s
-// RUN: llvm-objdump -d %t2 -start-address=17825818 -stop-address=17825828 -triple=thumbv7a-linux-gnueabihf  | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d %t2 -start-address=17825812 -stop-address=17825826 -triple=thumbv7a-linux-gnueabihf  | FileCheck -check-prefix=CHECK3 %s
 // In this test case a branch that is in range and does not need its range
 // extended can be pushed out of range by another Thunk, necessitating another
 // pass
@@ -64,19 +64,15 @@
 // CHECK2-NEXT:  100000c:       c0 f2 00 1c     movt    r12, #256
 // CHECK2-NEXT:  1000010:       60 47   bx      r12
 // CHECK2: __Thumbv7ABSLongThunk_target:
-// CHECK2-NEXT:  1000012:       40 f2 1b 0c     movw    r12, #27
-// CHECK2-NEXT:  1000016:       c0 f2 10 1c     movt    r12, #272
-// CHECK2-NEXT:  100001a:       60 47   bx      r12
+// CHECK2-NEXT:  1000012:       ff f0 ff bf     b.w     #1048574 <target>
 // CHECK2: __Thumbv7ABSLongThunk_target2:
-// CHECK2-NEXT:  100001c:       40 f2 13 0c     movw    r12, #19
-// CHECK2-NEXT:  1000020:       c0 f2 10 0c     movt    r12, #16
-// CHECK2-NEXT:  1000024:       60 47   bx      r12
+// CHECK2-NEXT:  1000016:       ff f4 fc 97     b.w     #-15728648 <target2>
 
  .section .text.17, "ax", %progbits
 // Just enough space so that bl target is in range if no extension thunks are
 // generated.
 
- .space 0x100000 - 12
+ .space 0x100000 - 6
 
  .section .text.18, "ax", %progbits
  .thumb
@@ -90,7 +86,7 @@
  nop
  bx lr
 // CHECK3: target:
-// CHECK3-NEXT:  110001a:       ff f6 ff ff     bl      #-1048578
-// CHECK3-NEXT:  110001e:       00 bf   nop
-// CHECK3-NEXT:  1100020:       00 bf   nop
-// CHECK3-NEXT:  1100022:       70 47   bx      lr
+// CHECK3-NEXT:  1100014:       ff f6 ff ff     bl      #-1048578
+// CHECK3-NEXT:  1100018:       00 bf   nop
+// CHECK3-NEXT:  110001a:       00 bf   nop
+// CHECK3-NEXT:  110001c:       70 47   bx      lr
diff --git a/test/ELF/basic-ppc64.s b/test/ELF/basic-ppc64.s
new file mode 100644
index 0000000..5b9896d
--- /dev/null
+++ b/test/ELF/basic-ppc64.s
@@ -0,0 +1,323 @@
+# # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t
+# RUN: ld.lld --hash-style=sysv -discard-all -shared %t -o %t2
+# RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s
+# REQUIRES: ppc
+.abiversion 2
+# Exits with return code 55 on linux.
+.text
+  li 0,1
+  li 3,55
+  sc
+
+// CHECK:Format: ELF64-ppc64
+// CHECK-NEXT:Arch: powerpc64le
+// CHECK-NEXT:AddressSize: 64bit
+// CHECK-NEXT:LoadName: 
+// CHECK-NEXT:ElfHeader {
+// CHECK-NEXT:  Ident {
+// CHECK-NEXT:    Magic: (7F 45 4C 46)
+// CHECK-NEXT:    Class: 64-bit (0x2)
+// CHECK-NEXT:    DataEncoding: LittleEndian (0x1)
+// CHECK-NEXT:    FileVersion: 1
+// CHECK-NEXT:    OS/ABI: SystemV (0x0)
+// CHECK-NEXT:    ABIVersion: 0
+// CHECK-NEXT:    Unused: (00 00 00 00 00 00 00)
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Type: SharedObject (0x3)
+// CHECK-NEXT:  Machine: EM_PPC64 (0x15)
+// CHECK-NEXT:  Version: 1
+// CHECK-NEXT:  Entry: 0x10000
+// CHECK-NEXT:  ProgramHeaderOffset: 0x40
+// CHECK-NEXT:  SectionHeaderOffset:
+// CHECK-NEXT:  Flags [ (0x2)
+// CHECK-NEXT:    0x2
+// CHECK-NEXT:  ]
+// CHECK-NEXT:  HeaderSize: 64
+// CHECK-NEXT:  ProgramHeaderEntrySize: 56
+// CHECK-NEXT:  ProgramHeaderCount: 7
+// CHECK-NEXT:  SectionHeaderEntrySize: 64
+// CHECK-NEXT:  SectionHeaderCount: 10
+// CHECK-NEXT:  StringTableSectionIndex: 8
+// CHECK-NEXT:}
+// CHECK-NEXT:Sections [
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 0
+// CHECK-NEXT:    Name:  (0)
+// CHECK-NEXT:    Type: SHT_NULL (0x0)
+// CHECK-NEXT:    Flags [ (0x0)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x0
+// CHECK-NEXT:    Offset: 0x0
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Link: 0
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 0
+// CHECK-NEXT:    EntrySize: 0
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 1
+// CHECK-NEXT:    Name: .dynsym (1)
+// CHECK-NEXT:    Type: SHT_DYNSYM (0xB)
+// CHECK-NEXT:    Flags [ (0x2)
+// CHECK-NEXT:      SHF_ALLOC (0x2)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x1C8
+// CHECK-NEXT:    Offset: 0x1C8
+// CHECK-NEXT:    Size: 24
+// CHECK-NEXT:    Link: 3
+// CHECK-NEXT:    Info: 1
+// CHECK-NEXT:    AddressAlignment: 8
+// CHECK-NEXT:    EntrySize: 24
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 00000000 00000000 00000000 00000000  |................|
+// CHECK-NEXT:      0010: 00000000 00000000                    |........|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 2
+// CHECK-NEXT:    Name: .hash (9)
+// CHECK-NEXT:    Type: SHT_HASH (0x5)
+// CHECK-NEXT:    Flags [ (0x2)
+// CHECK-NEXT:      SHF_ALLOC (0x2)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x1E0
+// CHECK-NEXT:    Offset: 0x1E0
+// CHECK-NEXT:    Size: 16
+// CHECK-NEXT:    Link: 1
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 4
+// CHECK-NEXT:    EntrySize: 4
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 01000000 01000000 00000000 00000000  |................|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 3
+// CHECK-NEXT:    Name: .dynstr (15)
+// CHECK-NEXT:    Type: SHT_STRTAB (0x3)
+// CHECK-NEXT:    Flags [ (0x2)
+// CHECK-NEXT:      SHF_ALLOC (0x2)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x1F0
+// CHECK-NEXT:    Offset: 0x1F0
+// CHECK-NEXT:    Size: 1
+// CHECK-NEXT:    Link: 0
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 1
+// CHECK-NEXT:    EntrySize: 0
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 00                                   |.|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 4
+// CHECK-NEXT:    Name: .text (23)
+// CHECK-NEXT:    Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT:    Flags [ (0x6)
+// CHECK-NEXT:      SHF_ALLOC (0x2)
+// CHECK-NEXT:      SHF_EXECINSTR (0x4)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x10000
+// CHECK-NEXT:    Offset: 0x10000
+// CHECK-NEXT:    Size: 12
+// CHECK-NEXT:    Link: 0
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 4
+// CHECK-NEXT:    EntrySize: 0
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 01000038 37006038 02000044           |...87.`8...D|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 5
+// CHECK-NEXT:    Name: .dynamic (29)
+// CHECK-NEXT:    Type: SHT_DYNAMIC (0x6)
+// CHECK-NEXT:    Flags [ (0x3)
+// CHECK-NEXT:      SHF_ALLOC (0x2)
+// CHECK-NEXT:      SHF_WRITE (0x1)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x20000
+// CHECK-NEXT:    Offset: 0x20000
+// CHECK-NEXT:    Size: 96
+// CHECK-NEXT:    Link: 3
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 8
+// CHECK-NEXT:    EntrySize: 16
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 06000000 00000000 C8010000 00000000  |................|
+// CHECK-NEXT:      0010: 0B000000 00000000 18000000 00000000  |................|
+// CHECK-NEXT:      0020: 05000000 00000000 F0010000 00000000  |................|
+// CHECK-NEXT:      0030: 0A000000 00000000 01000000 00000000  |................|
+// CHECK-NEXT:      0040: 04000000 00000000 E0010000 00000000  |................|
+// CHECK-NEXT:      0050: 00000000 00000000 00000000 00000000  |................|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 6
+// CHECK-NEXT:    Name: .comment (38)
+// CHECK-NEXT:    Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT:    Flags [ (0x30)
+// CHECK-NEXT:      SHF_MERGE (0x10)
+// CHECK-NEXT:      SHF_STRINGS (0x20)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x0
+// CHECK-NEXT:    Offset: 0x20060
+// CHECK-NEXT:    Size: 8
+// CHECK-NEXT:    Link: 0
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 1
+// CHECK-NEXT:    EntrySize: 1
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 4C4C4420 312E3000 |LLD 1.0.|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 7
+// CHECK-NEXT:    Name: .symtab (47)
+// CHECK-NEXT:    Type: SHT_SYMTAB (0x2)
+// CHECK-NEXT:    Flags [ (0x0)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x0
+// CHECK-NEXT:    Offset: 0x20068
+// CHECK-NEXT:    Size: 48
+// CHECK-NEXT:    Link: 9
+// CHECK-NEXT:    Info: 2
+// CHECK-NEXT:    AddressAlignment: 8
+// CHECK-NEXT:    EntrySize: 24
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 00000000 00000000 00000000 00000000  |................|
+// CHECK-NEXT:      0010: 00000000 00000000 01000000 00020500  |................|
+// CHECK-NEXT:      0020: 00000200 00000000 00000000 00000000  |................|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 8
+// CHECK-NEXT:    Name: .shstrtab (55)
+// CHECK-NEXT:    Type: SHT_STRTAB (0x3)
+// CHECK-NEXT:    Flags [ (0x0)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x0
+// CHECK-NEXT:    Offset: 0x20098
+// CHECK-NEXT:    Size: 73
+// CHECK-NEXT:    Link: 0
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 1
+// CHECK-NEXT:    EntrySize: 0
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 002E6479 6E73796D 002E6861 7368002E  |..dynsym..hash..|
+// CHECK-NEXT:      0010: 64796E73 7472002E 74657874 002E6479  |dynstr..text..dy|
+// CHECK-NEXT:      0020: 6E616D69 63002E63 6F6D6D65 6E74002E  |namic..comment..|
+// CHECK-NEXT:      0030: 73796D74 6162002E 73687374 72746162  |symtab..shstrtab|
+// CHECK-NEXT:      0040: 002E7374 72746162 00                 |..strtab.|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Section {
+// CHECK-NEXT:    Index: 9
+// CHECK-NEXT:    Name: .strtab (65)
+// CHECK-NEXT:    Type: SHT_STRTAB (0x3)
+// CHECK-NEXT:    Flags [ (0x0)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Address: 0x0
+// CHECK-NEXT:    Offset: 0x200E1
+// CHECK-NEXT:    Size: 10
+// CHECK-NEXT:    Link: 0
+// CHECK-NEXT:    Info: 0
+// CHECK-NEXT:    AddressAlignment: 1
+// CHECK-NEXT:    EntrySize: 0
+// CHECK-NEXT:    SectionData (
+// CHECK-NEXT:      0000: 005F4459 4E414D49 4300               |._DYNAMIC.|
+// CHECK-NEXT:    )
+// CHECK-NEXT:  }
+// CHECK-NEXT:]
+// CHECK-NEXT:ProgramHeaders [
+// CHECK-NEXT:  ProgramHeader {
+// CHECK-NEXT:    Type: PT_PHDR (0x6)
+// CHECK-NEXT:    Offset: 0x40
+// CHECK-NEXT:    VirtualAddress: 0x40
+// CHECK-NEXT:    PhysicalAddress: 0x40
+// CHECK-NEXT:    FileSize: 392
+// CHECK-NEXT:    MemSize: 392
+// CHECK-NEXT:    Flags [ (0x4)
+// CHECK-NEXT:      PF_R (0x4)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Alignment: 8
+// CHECK-NEXT:  }
+// CHECK-NEXT:  ProgramHeader {
+// CHECK-NEXT:    Type: PT_LOAD (0x1)
+// CHECK-NEXT:    Offset: 0x0
+// CHECK-NEXT:    VirtualAddress: 0x0
+// CHECK-NEXT:    PhysicalAddress: 0x0
+// CHECK-NEXT:    FileSize: 497
+// CHECK-NEXT:    MemSize: 497
+// CHECK-NEXT:    Flags [ (0x4)
+// CHECK-NEXT:      PF_R (0x4)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Alignment: 65536
+// CHECK-NEXT:  }
+// CHECK-NEXT:  ProgramHeader {
+// CHECK-NEXT:    Type: PT_LOAD (0x1)
+// CHECK-NEXT:    Offset: 0x10000
+// CHECK-NEXT:    VirtualAddress: 0x10000
+// CHECK-NEXT:    PhysicalAddress: 0x10000
+// CHECK-NEXT:    FileSize: 12
+// CHECK-NEXT:    MemSize: 12
+// CHECK-NEXT:    Flags [ (0x5)
+// CHECK-NEXT:      PF_R (0x4)
+// CHECK-NEXT:      PF_X (0x1)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Alignment: 65536
+// CHECK-NEXT:  }
+// CHECK-NEXT:  ProgramHeader {
+// CHECK-NEXT:    Type: PT_LOAD (0x1)
+// CHECK-NEXT:    Offset: 0x20000
+// CHECK-NEXT:    VirtualAddress: 0x20000
+// CHECK-NEXT:    PhysicalAddress: 0x20000
+// CHECK-NEXT:    FileSize: 96
+// CHECK-NEXT:    MemSize: 96
+// CHECK-NEXT:    Flags [ (0x6)
+// CHECK-NEXT:      PF_R (0x4)
+// CHECK-NEXT:      PF_W (0x2)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Alignment: 65536
+// CHECK-NEXT:  }
+// CHECK-NEXT:  ProgramHeader {
+// CHECK-NEXT:    Type: PT_DYNAMIC (0x2)
+// CHECK-NEXT:    Offset: 0x20000
+// CHECK-NEXT:    VirtualAddress: 0x20000
+// CHECK-NEXT:    PhysicalAddress: 0x20000
+// CHECK-NEXT:    FileSize: 96
+// CHECK-NEXT:    MemSize: 96
+// CHECK-NEXT:    Flags [ (0x6)
+// CHECK-NEXT:      PF_R (0x4)
+// CHECK-NEXT:      PF_W (0x2)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Alignment: 8
+// CHECK-NEXT:  }
+// CHECK-NEXT:  ProgramHeader {
+// CHECK-NEXT:    Type: PT_GNU_RELRO (0x6474E552)
+// CHECK-NEXT:    Offset: 0x20000
+// CHECK-NEXT:    VirtualAddress: 0x20000
+// CHECK-NEXT:    PhysicalAddress: 0x20000
+// CHECK-NEXT:    FileSize: 96
+// CHECK-NEXT:    MemSize: 4096
+// CHECK-NEXT:    Flags [ (0x4)
+// CHECK-NEXT:      PF_R (0x4)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Alignment: 1
+// CHECK-NEXT:  }
+// CHECK-NEXT:  ProgramHeader {
+// CHECK-NEXT:    Type: PT_GNU_STACK (0x6474E551)
+// CHECK-NEXT:    Offset: 0x0
+// CHECK-NEXT:    VirtualAddress: 0x0
+// CHECK-NEXT:    PhysicalAddress: 0x0
+// CHECK-NEXT:    FileSize: 0
+// CHECK-NEXT:    MemSize: 0
+// CHECK-NEXT:    Flags [ (0x6)
+// CHECK-NEXT:      PF_R (0x4)
+// CHECK-NEXT:      PF_W (0x2)
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Alignment: 0
+// CHECK-NEXT:  }
+// CHECK-NEXT:]
diff --git a/test/ELF/basic64be.s b/test/ELF/basic64be.s
index d16f4a0..03a4a1f 100644
--- a/test/ELF/basic64be.s
+++ b/test/ELF/basic64be.s
@@ -39,7 +39,8 @@
 # CHECK-NEXT:   Entry: 0x10020040
 # CHECK-NEXT:   ProgramHeaderOffset: 0x40
 # CHECK-NEXT:   SectionHeaderOffset: 0x30080
-# CHECK-NEXT:   Flags [ (0x0)
+# CHECK-NEXT:   Flags [ (0x1)
+# CHECK-NEXT:    0x1
 # CHECK-NEXT:   ]
 # CHECK-NEXT:   HeaderSize: 64
 # CHECK-NEXT:   ProgramHeaderEntrySize: 56
diff --git a/test/ELF/compressed-debug-conflict.s b/test/ELF/compressed-debug-conflict.s
index c67bc92..f7ddd2d 100644
--- a/test/ELF/compressed-debug-conflict.s
+++ b/test/ELF/compressed-debug-conflict.s
@@ -5,11 +5,11 @@
 
 # OBJ:      Sections [
 # OBJ:        Section {
-# OBJ:          Index: 3
-# OBJ-NEXT:     Name: .debug_line (16)
-# OBJ-NEXT:     Type: SHT_PROGBITS (0x1)
-# OBJ-NEXT:     Flags [ (0x800)
-# OBJ-NEXT:       SHF_COMPRESSED (0x800)
+# OBJ:          Index:
+# OBJ:          Name: .debug_line
+# OBJ-NEXT:     Type: SHT_PROGBITS
+# OBJ-NEXT:     Flags [
+# OBJ-NEXT:       SHF_COMPRESSED
 # OBJ-NEXT:     ]
 
 # ERROR:      error: duplicate symbol: main
@@ -27,3 +27,24 @@
 	xorl	%eax, %eax
 	retl
 	.file	2 "/tmp/repeat/repeat/repeat/repeat" "repeat.h"
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.byte	17                      # DW_TAG_compile_unit
+	.byte	0                       # DW_CHILDREN_no
+	.byte	16                      # DW_AT_stmt_list
+	.byte	23                      # DW_FORM_sec_offset
+	.byte	0                       # EOM(1)
+	.byte	0                       # EOM(2)
+	.byte	0                       # EOM(3)
+
+        .section	.debug_info,"",@progbits
+	.long	.Lend0 - .Lbegin0       # Length of Unit
+.Lbegin0:
+	.short	4                       # DWARF version number
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+	.byte	4                       # Address Size (in bytes)
+	.byte	1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+	.long	.debug_line             # DW_AT_stmt_list
+.Lend0:
+	.section	.debug_line,"",@progbits
diff --git a/test/ELF/conflict-debug-variable.s b/test/ELF/conflict-debug-variable.s
index 297ed4b..409c38e 100644
--- a/test/ELF/conflict-debug-variable.s
+++ b/test/ELF/conflict-debug-variable.s
@@ -7,14 +7,14 @@
 # INPUT-NEXT:    DW_AT_name      ("foo")
 # INPUT-NEXT:    DW_AT_decl_file ("1.c")
 # INPUT-NEXT:    DW_AT_decl_line (1)
-# INPUT-NEXT:    DW_AT_type      (cu + 0x0032 "int")
+# INPUT-NEXT:    DW_AT_type      (0x00000032 "int")
 # INPUT-NEXT:    DW_AT_external  (true)
 # INPUT-NEXT:    DW_AT_location  (DW_OP_addr 0x0)
 # INPUT:       DW_TAG_variable
 # INPUT-NEXT:    DW_AT_name      ("bar")
 # INPUT-NEXT:    DW_AT_decl_file ("1.c")
 # INPUT-NEXT:    DW_AT_decl_line (2)
-# INPUT-NEXT:    DW_AT_type      (cu + 0x0032 "int")
+# INPUT-NEXT:    DW_AT_type      (0x00000032 "int")
 # INPUT-NEXT:    DW_AT_external  (true)
 # INPUT-NEXT:    DW_AT_location  (DW_OP_addr 0x0)
 
diff --git a/test/ELF/copy-in-shared.s b/test/ELF/copy-in-shared.s
index 7043985..6af54c1 100644
--- a/test/ELF/copy-in-shared.s
+++ b/test/ELF/copy-in-shared.s
@@ -4,7 +4,7 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
 // RUN: not ld.lld %t2.o %t1.so -o %t2.so -shared 2>&1 | FileCheck %s
 
-// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: foo in readonly segment
+// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.so
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
 
diff --git a/test/ELF/copy-rel-pie-error.s b/test/ELF/copy-rel-pie-error.s
index 6f7677e..e2fd5b5 100644
--- a/test/ELF/copy-rel-pie-error.s
+++ b/test/ELF/copy-rel-pie-error.s
@@ -3,11 +3,11 @@
 // RUN: ld.lld %t2.o -o %t2.so -shared
 // RUN: not ld.lld %t.o %t2.so -o %t.exe -pie 2>&1 | FileCheck %s
 
-// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: bar
+// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: bar in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.so
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
 
-// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: foo
+// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.so
 // CHECK: >>> referenced by {{.*}}.o:(.text+0x8)
 
diff --git a/test/ELF/cref.s b/test/ELF/cref.s
new file mode 100644
index 0000000..01516fa
--- /dev/null
+++ b/test/ELF/cref.s
@@ -0,0 +1,26 @@
+// REQUIRES: x86
+
+// RUN: echo '.global foo; foo:' | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t1.o
+// RUN: echo '.global foo, bar; bar:' | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t3.o
+// RUN: ld.lld -shared -o %t1.so %t1.o -gc-sections
+// RUN: ld.lld -o /dev/null %t1.so %t2.o %t3.o -cref | FileCheck -strict-whitespace %s
+
+//      CHECK: Symbol                                            File
+// CHECK-NEXT: bar                                               {{.*}}2.o
+// CHECK-NEXT:                                                   {{.*}}3.o
+// CHECK-NEXT: foo                                               {{.*}}1.so
+// CHECK-NEXT:                                                   {{.*}}2.o
+// CHECK-NEXT:                                                   {{.*}}3.o
+// CHECK-NEXT: _start                                            {{.*}}3.o
+// CHECK-NEXT: baz                                               {{.*}}3.o
+
+.global _start, foo, bar, baz
+_start:
+  call foo
+  call bar
+localsym:
+baz:
+
+.section .text.a,"ax",@progbits
+discarded:
diff --git a/test/ELF/dynamic-got.s b/test/ELF/dynamic-got.s
index 385394b..844e4f4 100644
--- a/test/ELF/dynamic-got.s
+++ b/test/ELF/dynamic-got.s
@@ -3,6 +3,23 @@
 // RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
 // RUN: llvm-readobj -s -l -section-data -r %t.so | FileCheck %s
 
+// CHECK:     Name: .got.plt
+// CHECK-NEXT:     Type: SHT_PROGBITS
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:       SHF_WRITE
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address:
+// CHECK-NEXT:     Offset:
+// CHECK-NEXT:     Size:
+// CHECK-NEXT:     Link:
+// CHECK-NEXT:     Info:
+// CHECK-NEXT:     AddressAlignment:
+// CHECK-NEXT:     EntrySize:
+// CHECK-NEXT:     SectionData (
+// CHECK-NEXT:       0000: 00300000 00000000 00000000
+// CHECK-NEXT:     )
+
 // CHECK:      Name: .got
 // CHECK-NEXT: Type: SHT_PROGBITS
 // CHECK-NEXT: Flags [
@@ -17,19 +34,19 @@
 // CHECK-NEXT: AddressAlignment:
 // CHECK-NEXT: EntrySize:
 // CHECK-NEXT: SectionData (
-// CHECK-NEXT:   0000: 00200000                |
+// CHECK-NEXT:   0000: 00300000
 // CHECK-NEXT: )
 
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rel.dyn {
-// CHECK-NEXT:     0x2050 R_386_RELATIVE - 0x0
+// CHECK-NEXT:     0x3050 R_386_RELATIVE - 0x0
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
 // CHECK:      Type: PT_DYNAMIC
-// CHECK-NEXT: Offset: 0x2000
-// CHECK-NEXT: VirtualAddress: 0x2000
-// CHECK-NEXT: PhysicalAddress: 0x2000
+// CHECK-NEXT: Offset: 0x3000
+// CHECK-NEXT: VirtualAddress: 0x3000
+// CHECK-NEXT: PhysicalAddress: 0x3000
 
         calll   .L0$pb
 .L0$pb:
diff --git a/test/ELF/dynamic-no-rosegment.s b/test/ELF/dynamic-no-rosegment.s
index e5ad26e..f2b5f35 100644
--- a/test/ELF/dynamic-no-rosegment.s
+++ b/test/ELF/dynamic-no-rosegment.s
@@ -7,9 +7,9 @@
 # CHECK-NEXT:   Tag                Type                 Name/Value
 # CHECK-NEXT:   0x0000000000000006 SYMTAB               0x120
 # CHECK-NEXT:   0x000000000000000B SYMENT               24 (bytes)
-# CHECK-NEXT:   0x0000000000000005 STRTAB               0x1D0
+# CHECK-NEXT:   0x0000000000000005 STRTAB               0x1D8
 # CHECK-NEXT:   0x000000000000000A STRSZ                1 (bytes)
 # CHECK-NEXT:   0x000000006FFFFEF5 GNU_HASH             0x138
-# CHECK-NEXT:   0x0000000000000004 HASH                 0x150
+# CHECK-NEXT:   0x0000000000000004 HASH                 0x154
 # CHECK-NEXT:   0x0000000000000000 NULL                 0x0
 # CHECK-NEXT: ]
diff --git a/test/ELF/dynamic-reloc-in-ro.s b/test/ELF/dynamic-reloc-in-ro.s
index ecdbfeb..4dee4f6 100644
--- a/test/ELF/dynamic-reloc-in-ro.s
+++ b/test/ELF/dynamic-reloc-in-ro.s
@@ -2,7 +2,7 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
 
-// CHECK:      can't create dynamic relocation R_X86_64_64 against local symbol in readonly segment; recompile object files with -fPIC
+// CHECK:      can't create dynamic relocation R_X86_64_64 against local symbol in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK-NEXT: >>> defined in {{.*}}.o
 // CHECK-NEXT: >>> referenced by {{.*}}.o:(.text+0x0)
 
diff --git a/test/ELF/eh-frame-dyn-rel.s b/test/ELF/eh-frame-dyn-rel.s
index 289e6c0..a244ac6 100644
--- a/test/ELF/eh-frame-dyn-rel.s
+++ b/test/ELF/eh-frame-dyn-rel.s
@@ -2,7 +2,7 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 // RUN: not ld.lld %t.o %t.o -o %t -shared 2>&1 | FileCheck %s
 
-// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: foo
+// CHECK: can't create dynamic relocation R_X86_64_64 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 // CHECK: >>> defined in {{.*}}.o
 // CHECK: >>> referenced by {{.*}}.o:(.eh_frame+0x12)
 
diff --git a/test/ELF/eh-frame-hdr-augmentation.s b/test/ELF/eh-frame-hdr-augmentation.s
index 135f811..934f920 100644
--- a/test/ELF/eh-frame-hdr-augmentation.s
+++ b/test/ELF/eh-frame-hdr-augmentation.s
@@ -11,6 +11,7 @@
 // CHECK-NEXT:   Code alignment factor: 1
 // CHECK-NEXT:   Data alignment factor: -8
 // CHECK-NEXT:   Return address column: 16
+// CHECK-NEXT:   Personality Address: 00000dad
 // CHECK-NEXT:   Augmentation data:
 
 // CHECK:      DW_CFA_def_cfa:  reg7 +8
@@ -19,6 +20,7 @@
 // CHECK-NEXT: DW_CFA_nop:
 
 // CHECK:      00000020 00000014 00000024 FDE cie=00000024 pc=00000d98...00000d98
+// CHECK-NEXT:   LSDA Address: 00000d8f
 // CHECK-NEXT:   DW_CFA_nop:
 // CHECK-NEXT:   DW_CFA_nop:
 // CHECK-NEXT:   DW_CFA_nop:
diff --git a/test/ELF/elf-header.s b/test/ELF/elf-header.s
new file mode 100644
index 0000000..e188650
--- /dev/null
+++ b/test/ELF/elf-header.s
@@ -0,0 +1,18 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t1
+# RUN: llvm-readobj -file-headers %t1 | FileCheck %s
+
+# RUN: ld.lld %t.o -no-rosegment -o %t2
+# RUN: llvm-readobj -file-headers %t2 | FileCheck %s
+
+# CHECK:      ElfHeader {
+# CHECK-NEXT:   Ident {
+# CHECK-NEXT:     Magic: (7F 45 4C 46)
+# CHECK-NEXT:     Class: 64-bit (0x2)
+# CHECK-NEXT:     DataEncoding: LittleEndian (0x1)
+# CHECK-NEXT:     FileVersion: 1
+# CHECK-NEXT:     OS/ABI: SystemV (0x0)
+# CHECK-NEXT:     ABIVersion: 0
+# CHECK-NEXT:     Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT:   }
diff --git a/test/ELF/emit-relocs-eh-frame.s b/test/ELF/emit-relocs-eh-frame.s
new file mode 100644
index 0000000..4df8858
--- /dev/null
+++ b/test/ELF/emit-relocs-eh-frame.s
@@ -0,0 +1,16 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: ld.lld --emit-relocs %t1.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# CHECK:      Relocations [
+# CHECK-NEXT:   Section {{.*}} .rela.eh_frame {
+# CHECK-NEXT:     0x{{.*}} R_X86_64_PC32 .text 0x0
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+.text
+.globl foo
+foo:
+ .cfi_startproc
+ .cfi_endproc
diff --git a/test/ELF/emit-relocs-shared.s b/test/ELF/emit-relocs-shared.s
index 65a12c1..cb87d9f 100644
--- a/test/ELF/emit-relocs-shared.s
+++ b/test/ELF/emit-relocs-shared.s
@@ -7,10 +7,10 @@
 .quad foo
 
 # CHECK:      Relocations [
-# CHECK-NEXT:   Section (4) .rela.dyn {
+# CHECK-NEXT:   Section {{.*}} .rela.dyn {
 # CHECK-NEXT:     0x1000 R_X86_64_64 foo 0x0
 # CHECK-NEXT:   }
-# CHECK-NEXT:   Section (8) .rela.data {
+# CHECK-NEXT:   Section {{.*}} .rela.data {
 # CHECK-NEXT:     0x1000 R_X86_64_64 foo 0x0
 # CHECK-NEXT:   }
 # CHECK-NEXT: ]
diff --git a/test/ELF/emit-relocs.s b/test/ELF/emit-relocs.s
index 95e70d8..b91bb9a 100644
--- a/test/ELF/emit-relocs.s
+++ b/test/ELF/emit-relocs.s
@@ -13,7 +13,7 @@
 
 # CHECK:      Section {
 # CHECK:        Index: 2
-# CHECK-NEXT:   Name: .rela.text
+# CHECK:        Name: .rela.text
 # CHECK-NEXT:   Type: SHT_RELA
 # CHECK-NEXT:   Flags [
 # CHECK-NEXT:     SHF_INFO_LINK
diff --git a/test/ELF/emulation.s b/test/ELF/emulation.s
index b3d0434..c176cc1 100644
--- a/test/ELF/emulation.s
+++ b/test/ELF/emulation.s
@@ -208,7 +208,8 @@
 # PPC64-NEXT:   Entry:
 # PPC64-NEXT:   ProgramHeaderOffset: 0x40
 # PPC64-NEXT:   SectionHeaderOffset:
-# PPC64-NEXT:   Flags [ (0x0)
+# PPC64-NEXT:   Flags [ (0x1)
+# PPC64-NEXT:     0x1
 # PPC64-NEXT:   ]
 # PPC64-NEXT:   HeaderSize: 64
 # PPC64-NEXT:   ProgramHeaderEntrySize: 56
@@ -218,6 +219,38 @@
 # PPC64-NEXT:   StringTableSectionIndex:
 # PPC64-NEXT: }
 
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %tppc64le
+# RUN: ld.lld -m elf64lppc %tppc64le -o %t2ppc64le
+# RUN: llvm-readobj -file-headers %t2ppc64le | FileCheck --check-prefix=PPC64LE %s
+# RUN: ld.lld %tppc64le -o %t3ppc64le
+# RUN: llvm-readobj -file-headers %t3ppc64le | FileCheck --check-prefix=PPC64LE %s
+# PPC64LE:      ElfHeader {
+# PPC64LE-NEXT:   Ident {
+# PPC64LE-NEXT:     Magic: (7F 45 4C 46)
+# PPC64LE-NEXT:     Class: 64-bit (0x2)
+# PPC64LE-NEXT:     DataEncoding: LittleEndian (0x1)
+# PPC64LE-NEXT:     FileVersion: 1
+# PPC64LE-NEXT:     OS/ABI: SystemV (0x0)
+# PPC64LE-NEXT:     ABIVersion: 0
+# PPC64LE-NEXT:     Unused: (00 00 00 00 00 00 00)
+# PPC64LE-NEXT:   }
+# PPC64LE-NEXT:   Type: Executable (0x2)
+# PPC64LE-NEXT:   Machine: EM_PPC64 (0x15)
+# PPC64LE-NEXT:   Version: 1
+# PPC64LE-NEXT:   Entry:
+# PPC64LE-NEXT:   ProgramHeaderOffset: 0x40
+# PPC64LE-NEXT:   SectionHeaderOffset:
+# PPC64LE-NEXT:   Flags [ (0x2)
+# PPC64LE-NEXT:     0x2
+# PPC64LE-NEXT:   ]
+# PPC64LE-NEXT:   HeaderSize: 64
+# PPC64LE-NEXT:   ProgramHeaderEntrySize: 56
+# PPC64LE-NEXT:   ProgramHeaderCount:
+# PPC64LE-NEXT:   SectionHeaderEntrySize: 64
+# PPC64LE-NEXT:   SectionHeaderCount:
+# PPC64LE-NEXT:   StringTableSectionIndex:
+# PPC64LE-NEXT: }
+
 # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %tmips
 # RUN: ld.lld -m elf32btsmip -e _start %tmips -o %t2mips
 # RUN: llvm-readobj -file-headers %t2mips | FileCheck --check-prefix=MIPS %s
diff --git a/test/ELF/global-offset-table-position-aarch64.s b/test/ELF/global-offset-table-position-aarch64.s
index 68bc4a4..8e26913 100644
--- a/test/ELF/global-offset-table-position-aarch64.s
+++ b/test/ELF/global-offset-table-position-aarch64.s
@@ -20,11 +20,11 @@
 .long _GLOBAL_OFFSET_TABLE_ - .
 
 // CHECK: Name: _GLOBAL_OFFSET_TABLE_ (11)
-// CHECK-NEXT:     Value: 0x30090
+// CHECK-NEXT:     Value: 0x20008
 // CHECK-NEXT:     Size: 0
 // CHECK-NEXT:     Binding: Local (0x0)
 // CHECK-NEXT:     Type: None (0x0)
 // CHECK-NEXT:     Other [ (0x2)
 // CHECK-NEXT:       STV_HIDDEN (0x2)
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Section: .got
+// CHECK-NEXT:     Section: .got.plt
diff --git a/test/ELF/global-offset-table-position-i386.s b/test/ELF/global-offset-table-position-i386.s
index 9f778e1..8d50b49 100644
--- a/test/ELF/global-offset-table-position-i386.s
+++ b/test/ELF/global-offset-table-position-i386.s
@@ -3,7 +3,8 @@
 // RUN: llvm-readobj -t %t2 | FileCheck %s
 // REQUIRES: x86
 
-// The X86 _GLOBAL_OFFSET_TABLE_ is defined at the end of the .got section.
+// The X86 _GLOBAL_OFFSET_TABLE_ is defined at the start of the .got.plt
+// section.
 .globl  a
 .type   a,@object
 .comm   a,4,4
@@ -21,11 +22,11 @@
 calll   f@PLT
 
 // CHECK:     Name: _GLOBAL_OFFSET_TABLE_ (1)
-// CHECK-NEXT:     Value: 0x306C
+// CHECK-NEXT:     Value: 0x2000
 // CHECK-NEXT:     Size: 0
 // CHECK-NEXT:     Binding: Local (0x0)
 // CHECK-NEXT:     Type: None (0x0)
 // CHECK-NEXT:     Other [ (0x2)
 // CHECK-NEXT:       STV_HIDDEN (0x2)
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Section: .got (0xA)
+// CHECK-NEXT:     Section: .got.plt
diff --git a/test/ELF/global-offset-table-position.s b/test/ELF/global-offset-table-position.s
index f1195b2..57fe6c8 100644
--- a/test/ELF/global-offset-table-position.s
+++ b/test/ELF/global-offset-table-position.s
@@ -3,7 +3,8 @@
 // RUN: llvm-readobj -t %t2 | FileCheck %s
 // REQUIRES: x86
 
-// The X86_64 _GLOBAL_OFFSET_TABLE_ is defined at the end of the .got section.
+// The X86_64 _GLOBAL_OFFSET_TABLE_ is defined at the start of the .got.plt
+// section.
 .globl  a
 .type   a,@object
 .comm   a,4,4
@@ -21,11 +22,11 @@
 .long _GLOBAL_OFFSET_TABLE_ - .
 
 // CHECK:     Name: _GLOBAL_OFFSET_TABLE_
-// CHECK-NEXT:     Value: 0x30D8
+// CHECK-NEXT:     Value: 0x2008
 // CHECK-NEXT:     Size: 0
 // CHECK-NEXT:     Binding: Local
 // CHECK-NEXT:     Type: None (0x0)
 // CHECK-NEXT:     Other [
 // CHECK-NEXT:       STV_HIDDEN
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Section: .got
+// CHECK-NEXT:     Section: .got.plt
diff --git a/test/ELF/global_offset_table_shared.s b/test/ELF/global_offset_table_shared.s
index 03af02e..06bd7b3 100644
--- a/test/ELF/global_offset_table_shared.s
+++ b/test/ELF/global_offset_table_shared.s
@@ -4,11 +4,11 @@
 .long _GLOBAL_OFFSET_TABLE_ - .
 
 // CHECK:      Name: _GLOBAL_OFFSET_TABLE_
-// CHECK-NEXT: Value: 0x2060
+// CHECK-NEXT: Value: 0x2000
 // CHECK-NEXT: Size: 0
 // CHECK-NEXT: Binding: Local
 // CHECK-NEXT: Type: None
 // CHECK-NEXT: Other [ (0x2)
 // CHECK-NEXT: STV_HIDDEN (0x2)
 // CHECK-NEXT:    ]
-// CHECK-NEXT: Section: .got
+// CHECK-NEXT: Section: .got.plt
diff --git a/test/ELF/gnu-hash-table.s b/test/ELF/gnu-hash-table.s
index fa68ba2..e8fd059 100644
--- a/test/ELF/gnu-hash-table.s
+++ b/test/ELF/gnu-hash-table.s
@@ -51,12 +51,12 @@
 # EMPTY-NEXT:   }
 # EMPTY-NEXT: ]
 # EMPTY:      GnuHashTable {
-# EMPTY-NEXT:   Num Buckets: 0
+# EMPTY-NEXT:   Num Buckets: 1
 # EMPTY-NEXT:   First Hashed Symbol Index: 2
 # EMPTY-NEXT:   Num Mask Words: 1
-# EMPTY-NEXT:   Shift Count: 5
+# EMPTY-NEXT:   Shift Count: 6
 # EMPTY-NEXT:   Bloom Filter: [0x0]
-# EMPTY-NEXT:   Buckets: []
+# EMPTY-NEXT:   Buckets: [0]
 # EMPTY-NEXT:   Values: []
 # EMPTY-NEXT: }
 
@@ -113,8 +113,8 @@
 # I386-NEXT:   Num Buckets: 1
 # I386-NEXT:   First Hashed Symbol Index: 4
 # I386-NEXT:   Num Mask Words: 1
-# I386-NEXT:   Shift Count: 5
-# I386-NEXT:   Bloom Filter: [0x14000220]
+# I386-NEXT:   Shift Count: 6
+# I386-NEXT:   Bloom Filter: [0x4004204]
 # I386-NEXT:   Buckets: [4]
 # I386-NEXT:   Values: [0xB8860BA, 0xB887389]
 # I386-NEXT: }
diff --git a/test/ELF/gnu-ifunc-plt-i386.s b/test/ELF/gnu-ifunc-plt-i386.s
index 243eff6..d0d21e7 100644
--- a/test/ELF/gnu-ifunc-plt-i386.s
+++ b/test/ELF/gnu-ifunc-plt-i386.s
@@ -70,7 +70,7 @@
 
 .globl _start
 _start:
- call foo
- call bar
- call bar2
- call zed2
+ call foo@plt
+ call bar@plt
+ call bar2@plt
+ call zed2@plt
diff --git a/test/ELF/got32-i386.s b/test/ELF/got32-i386.s
index 00c7c0d..dce50d0 100644
--- a/test/ELF/got32-i386.s
+++ b/test/ELF/got32-i386.s
@@ -20,4 +20,4 @@
 # CHECK:  .got 00000004 0000000000012000
 
 # RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s --check-prefix=ERR
-# ERR: error: can't create dynamic relocation R_386_GOT32 against symbol: foo in readonly segment; recompile object files with -fPIC
+# ERR: error: can't create dynamic relocation R_386_GOT32 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
diff --git a/test/ELF/got32x-i386.s b/test/ELF/got32x-i386.s
index 1311472..610051e 100644
--- a/test/ELF/got32x-i386.s
+++ b/test/ELF/got32x-i386.s
@@ -33,15 +33,15 @@
 
 ## 73728 == 0x12000 == ADDR(.got)
 # CHECK:       _start:
-# CHECK-NEXT:   11001: 8b 05 {{.*}} movl 73728, %eax
-# CHECK-NEXT:   11007: 8b 1d {{.*}} movl 73728, %ebx
+# CHECK-NEXT:   11001: 8b 05 {{.*}} movl 77824, %eax
+# CHECK-NEXT:   11007: 8b 1d {{.*}} movl 77824, %ebx
 # CHECK-NEXT:   1100d: 8b 80 {{.*}} movl -4(%eax), %eax
 # CHECK-NEXT:   11013: 8b 83 {{.*}} movl -4(%ebx), %eax
 # CHECK: Sections:
 # CHECK:  Name Size     Address
-# CHECK:  .got 00000004 0000000000012000
+# CHECK:  .got 00000004 0000000000013000
 
 # RUN: not ld.lld %S/Inputs/i386-got32x-baseless.elf -o %t1 -pie 2>&1 | \
 # RUN:   FileCheck %s --check-prefix=ERR
-# ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC
-# ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC
+# ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
+# ERR: error: can't create dynamic relocation R_386_GOT32X against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
diff --git a/test/ELF/i386-gotpc.s b/test/ELF/i386-gotpc.s
index d2c5ef3..af8380b 100644
--- a/test/ELF/i386-gotpc.s
+++ b/test/ELF/i386-gotpc.s
@@ -6,15 +6,23 @@
 
 movl $_GLOBAL_OFFSET_TABLE_, %eax
 
+// CHECK:     Name: .got.plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT:   SHF_ALLOC
+// CHECK-NEXT:   SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2000
+
 // CHECK:      Name: .got
 // CHECK-NEXT: Type: SHT_PROGBITS
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_WRITE
 // CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x2030
+// CHECK-NEXT: Address: 0x3030
 
 // DISASM:      Disassembly of section .text:
 // DISASM-NEXT: .text:
-// DISASM-NEXT:    1000: {{.*}}         movl    $4144, %eax
-//                                              0x2030 - 0x1000 = 4144
+// DISASM-NEXT:    1000: {{.*}}         movl    $8240, %eax
+//                                              0x3030 - 0x1000 = 0x2030
diff --git a/test/ELF/i386-pic-plt.s b/test/ELF/i386-pic-plt.s
new file mode 100644
index 0000000..0d32436
--- /dev/null
+++ b/test/ELF/i386-pic-plt.s
@@ -0,0 +1,12 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %p/Inputs/i386-pic-plt.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: not ld.lld %t.o %t2.so -o %t -pie 2>&1 | FileCheck %s
+
+// CHECK: error: symbol 'foo' cannot be preempted; recompile with -fPIE
+
+.global _start
+_start:
+  call foo
diff --git a/test/ELF/i386-reloc-16.s b/test/ELF/i386-reloc-16.s
index d69e6fb..e9d4fbb 100644
--- a/test/ELF/i386-reloc-16.s
+++ b/test/ELF/i386-reloc-16.s
@@ -4,9 +4,10 @@
 // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %S/Inputs/x86-64-reloc-16-error.s -o %t2
 // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t
 // RUN: ld.lld -shared %t %t1 -o %t3
+// RUN: llvm-objdump -s %t3 | FileCheck %s
 
 // CHECK:      Contents of section .text:
-// CHECK-NEXT:   200000 42
+// CHECK-NEXT:   1000 42
 
 // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s
 // ERROR: relocation R_386_16 out of range: 65536 is not in [0, 65535]
diff --git a/test/ELF/i386-reloc-8.s b/test/ELF/i386-reloc-8.s
index c6ae671..e0e255b 100644
--- a/test/ELF/i386-reloc-8.s
+++ b/test/ELF/i386-reloc-8.s
@@ -4,9 +4,10 @@
 // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %S/Inputs/i386-reloc-8-error.s -o %t2
 // RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t
 // RUN: ld.lld -shared %t %t1 -o %t3
+// RUN: llvm-objdump -s %t3 | FileCheck %s
 
 // CHECK:      Contents of section .text:
-// CHECK-NEXT:   200000 42
+// CHECK-NEXT:   1000 ff
 
 // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s
 // ERROR: relocation R_386_8 out of range: 256 is not in [0, 255]
diff --git a/test/ELF/i386-retpoline-nopic-linkerscript.s b/test/ELF/i386-retpoline-nopic-linkerscript.s
new file mode 100644
index 0000000..0c7d1fc
--- /dev/null
+++ b/test/ELF/i386-retpoline-nopic-linkerscript.s
@@ -0,0 +1,67 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+
+// RUN: echo "SECTIONS { \
+// RUN:   .text : { *(.text) } \
+// RUN:   .plt : { *(.plt) } \
+// RUN:   .got.plt : { *(.got.plt) } \
+// RUN:   .dynstr : { *(.dynstr) } \
+// RUN: }" > %t.script
+// RUN: ld.lld %t1.o %t2.so -o %t.exe -z retpolineplt --script %t.script
+// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
+
+// CHECK:      Disassembly of section .plt:
+// CHECK-NEXT: .plt:
+// CHECK-NEXT: 10:       ff 35 fc 00 00 00       pushl   252
+// CHECK-NEXT: 16:       50      pushl   %eax
+// CHECK-NEXT: 17:       a1 00 01 00 00  movl    256, %eax
+// CHECK-NEXT: 1c:       e8 0f 00 00 00  calll   15 <.plt+0x20>
+// CHECK-NEXT: 21:       f3 90   pause
+// CHECK-NEXT: 23:       0f ae e8        lfence
+// CHECK-NEXT: 26:       eb f9   jmp     -7 <.plt+0x11>
+// CHECK-NEXT: 28:       cc      int3
+// CHECK-NEXT: 29:       cc      int3
+// CHECK-NEXT: 2a:       cc      int3
+// CHECK-NEXT: 2b:       cc      int3
+// CHECK-NEXT: 2c:       cc      int3
+// CHECK-NEXT: 2d:       cc      int3
+// CHECK-NEXT: 2e:       cc      int3
+// CHECK-NEXT: 2f:       cc      int3
+// CHECK-NEXT: 30:       89 0c 24        movl    %ecx, (%esp)
+// CHECK-NEXT: 33:       8b 4c 24 04     movl    4(%esp), %ecx
+// CHECK-NEXT: 37:       89 44 24 04     movl    %eax, 4(%esp)
+// CHECK-NEXT: 3b:       89 c8   movl    %ecx, %eax
+// CHECK-NEXT: 3d:       59      popl    %ecx
+// CHECK-NEXT: 3e:       c3      retl
+// CHECK-NEXT: 3f:       cc      int3
+// CHECK-NEXT: 40:       50      pushl   %eax
+// CHECK-NEXT: 41:       a1 04 01 00 00  movl    260, %eax
+// CHECK-NEXT: 46:       e8 e5 ff ff ff  calll   -27 <.plt+0x20>
+// CHECK-NEXT: 4b:       e9 d1 ff ff ff  jmp     -47 <.plt+0x11>
+// CHECK-NEXT: 50:       68 00 00 00 00  pushl   $0
+// CHECK-NEXT: 55:       e9 b6 ff ff ff  jmp     -74 <.plt>
+// CHECK-NEXT: 5a:       cc      int3
+// CHECK-NEXT: 5b:       cc      int3
+// CHECK-NEXT: 5c:       cc      int3
+// CHECK-NEXT: 5d:       cc      int3
+// CHECK-NEXT: 5e:       cc      int3
+// CHECK-NEXT: 5f:       cc      int3
+// CHECK-NEXT: 60:       50      pushl   %eax
+// CHECK-NEXT: 61:       a1 08 01 00 00  movl    264, %eax
+// CHECK-NEXT: 66:       e8 c5 ff ff ff  calll   -59 <.plt+0x20>
+// CHECK-NEXT: 6b:       e9 b1 ff ff ff  jmp     -79 <.plt+0x11>
+// CHECK-NEXT: 70:       68 08 00 00 00  pushl   $8
+// CHECK-NEXT: 75:       e9 96 ff ff ff  jmp     -106 <.plt>
+// CHECK-NEXT: 7a:       cc      int3
+// CHECK-NEXT: 7b:       cc      int3
+// CHECK-NEXT: 7c:       cc      int3
+// CHECK-NEXT: 7d:       cc      int3
+// CHECK-NEXT: 7e:       cc      int3
+// CHECK-NEXT: 7f:       cc      int3
+
+.global _start
+_start:
+  jmp bar@PLT
+  jmp zed@PLT
diff --git a/test/ELF/i386-retpoline-pic-linkerscript.s b/test/ELF/i386-retpoline-pic-linkerscript.s
new file mode 100644
index 0000000..049e53f
--- /dev/null
+++ b/test/ELF/i386-retpoline-pic-linkerscript.s
@@ -0,0 +1,64 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux -position-independent %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux -position-independent %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+
+// RUN: echo "SECTIONS { \
+// RUN:   .text : { *(.text) } \
+// RUN:   .plt : { *(.plt) } \
+// RUN:   .got.plt : { *(.got.plt) } \
+// RUN:   .dynstr : { *(.dynstr) } \
+// RUN: }" > %t.script
+// RUN: ld.lld %t1.o %t2.so -o %t.exe -z retpolineplt -pie --script %t.script
+// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
+
+// CHECK:      Disassembly of section .plt:
+// CHECK-NEXT: .plt:
+// CHECK-NEXT: 10:       ff b3 fc 00 00 00       pushl   252(%ebx)
+// CHECK-NEXT: 16:       50      pushl   %eax
+// CHECK-NEXT: 17:       8b 83 00 01 00 00       movl    256(%ebx), %eax
+// CHECK-NEXT: 1d:       e8 0e 00 00 00  calll   14 <.plt+0x20>
+// CHECK-NEXT: 22:       f3 90   pause
+// CHECK-NEXT: 24:       0f ae e8        lfence
+// CHECK-NEXT: 27:       eb f9   jmp     -7 <.plt+0x12>
+// CHECK-NEXT: 29:       cc      int3
+// CHECK-NEXT: 2a:       cc      int3
+// CHECK-NEXT: 2b:       cc      int3
+// CHECK-NEXT: 2c:       cc      int3
+// CHECK-NEXT: 2d:       cc      int3
+// CHECK-NEXT: 2e:       cc      int3
+// CHECK-NEXT: 2f:       cc      int3
+// CHECK-NEXT: 30:       89 0c 24        movl    %ecx, (%esp)
+// CHECK-NEXT: 33:       8b 4c 24 04     movl    4(%esp), %ecx
+// CHECK-NEXT: 37:       89 44 24 04     movl    %eax, 4(%esp)
+// CHECK-NEXT: 3b:       89 c8   movl    %ecx, %eax
+// CHECK-NEXT: 3d:       59      popl    %ecx
+// CHECK-NEXT: 3e:       c3      retl
+// CHECK-NEXT: 3f:       cc      int3
+// CHECK-NEXT: 40:       50      pushl   %eax
+// CHECK-NEXT: 41:       8b 83 04 01 00 00       movl    260(%ebx), %eax
+// CHECK-NEXT: 47:       e8 e4 ff ff ff  calll   -28 <.plt+0x20>
+// CHECK-NEXT: 4c:       e9 d1 ff ff ff  jmp     -47 <.plt+0x12>
+// CHECK-NEXT: 51:       68 00 00 00 00  pushl   $0
+// CHECK-NEXT: 56:       e9 b5 ff ff ff  jmp     -75 <.plt>
+// CHECK-NEXT: 5b:       cc      int3
+// CHECK-NEXT: 5c:       cc      int3
+// CHECK-NEXT: 5d:       cc      int3
+// CHECK-NEXT: 5e:       cc      int3
+// CHECK-NEXT: 5f:       cc      int3
+// CHECK-NEXT: 60:       50      pushl   %eax
+// CHECK-NEXT: 61:       8b 83 08 01 00 00       movl    264(%ebx), %eax
+// CHECK-NEXT: 67:       e8 c4 ff ff ff  calll   -60 <.plt+0x20>
+// CHECK-NEXT: 6c:       e9 b1 ff ff ff  jmp     -79 <.plt+0x12>
+// CHECK-NEXT: 71:       68 08 00 00 00  pushl   $8
+// CHECK-NEXT: 76:       e9 95 ff ff ff  jmp     -107 <.plt>
+// CHECK-NEXT: 7b:       cc      int3
+// CHECK-NEXT: 7c:       cc      int3
+// CHECK-NEXT: 7d:       cc      int3
+// CHECK-NEXT: 7e:       cc      int3
+// CHECK-NEXT: 7f:       cc      int3
+
+.global _start
+_start:
+  jmp bar@PLT
+  jmp zed@PLT
diff --git a/test/ELF/icf-merge2.s b/test/ELF/icf-merge2.s
new file mode 100644
index 0000000..47c4c88
--- /dev/null
+++ b/test/ELF/icf-merge2.s
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t --icf=all
+# RUN: llvm-objdump -d %t | FileCheck %s
+
+# Test that we don't merge these.
+# CHECK: leaq
+# CHECK: leaq
+
+        .section .merge1, "aM", @progbits, 8
+.Lfoo:
+        .quad 42
+
+        .section .merge2, "aM", @progbits, 4
+.Lbar:
+        .long 41
+
+        .section .text.foo, "ax", @progbits
+        leaq    .Lfoo(%rip), %rax
+
+        .section .text.bar, "ax", @progbits
+        leaq    .Lbar(%rip), %rax
diff --git a/test/ELF/icf-merged-sections.s b/test/ELF/icf-merged-sections.s
new file mode 100644
index 0000000..1f6e77e
--- /dev/null
+++ b/test/ELF/icf-merged-sections.s
@@ -0,0 +1,37 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t --icf=all --ignore-data-address-equality --print-icf-sections | FileCheck -allow-empty --check-prefix=NOICF %s
+# RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+# Check that merge synthetic sections are not merged by ICF.
+
+# NOICF-NOT: selected section <internal>:(.rodata)
+
+# CHECK:      Name: .rodata
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT:   SHF_ALLOC
+# CHECK-NEXT:   SHF_MERGE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size: 16
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT:   0000: 67452301 10325476 67452301 10325476
+
+.section .rodata.cst4,"aM",@progbits,4
+rodata4:
+  .long 0x01234567
+  .long 0x76543210
+  .long 0x01234567
+  .long 0x76543210
+
+.section .rodata.cst8,"aM",@progbits,8
+rodata8:
+  .long 0x01234567
+  .long 0x76543210
diff --git a/test/ELF/invalid/reloc-section-reordered.test b/test/ELF/invalid/reloc-section-reordered.test
new file mode 100644
index 0000000..7ff4ed6
--- /dev/null
+++ b/test/ELF/invalid/reloc-section-reordered.test
@@ -0,0 +1,30 @@
+# REQUIRES: x86
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: not ld.lld %t.o -o %t.exe 2>&1 | FileCheck %s
+# CHECK: unsupported relocation reference
+
+## YAML below lists .rela.text before .text, we do not support it.
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  OSABI:           ELFOSABI_FREEBSD
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Type:            SHT_REL
+    Name:            .rela.text
+    Link:            .symtab
+    Info:            .text
+    AddressAlign:    0x04
+    Relocations:
+      - Offset:          0
+        Symbol:          .text
+        Type:            R_X86_64_NONE
+  - Type:            SHT_PROGBITS
+    Name:            .text
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x04
+    Content:         "FFFFFFFFFFFFFFFF"
diff --git a/test/ELF/just-symbols-cref.s b/test/ELF/just-symbols-cref.s
new file mode 100644
index 0000000..8581c53
--- /dev/null
+++ b/test/ELF/just-symbols-cref.s
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t1.exe -Ttext=0x10000
+
+# RUN: ld.lld -just-symbols=%t1.exe -o %t2.exe -cref | FileCheck %s
+
+# CHECK:      Symbol      File
+# CHECK-NEXT: bar         {{.*exe}}
+# CHECK-NEXT: foo         {{.*exe}}
+
+.globl foo, bar
+foo:
+  ret
+
+.section .data
+.type bar, @object
+.size bar, 40
+bar:
+  .zero 40
diff --git a/test/ELF/just-symbols.s b/test/ELF/just-symbols.s
new file mode 100644
index 0000000..856cf8c
--- /dev/null
+++ b/test/ELF/just-symbols.s
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t1.exe -Ttext=0x10000
+
+# RUN: ld.lld -just-symbols=%t1.exe -o %t2.exe
+# RUN: llvm-readelf -symbols %t2.exe | FileCheck %s
+
+# CHECK: 0000000000011000    40 OBJECT  GLOBAL DEFAULT  ABS bar
+# CHECK: 0000000000010000     0 NOTYPE  GLOBAL DEFAULT  ABS foo
+
+.globl foo, bar
+foo:
+  ret
+
+.section .data
+.type bar, @object
+.size bar, 40
+bar:
+  .zero 40
diff --git a/test/ELF/linkerscript/Inputs/insert-after.s b/test/ELF/linkerscript/Inputs/insert-after.s
new file mode 100644
index 0000000..88a6044
--- /dev/null
+++ b/test/ELF/linkerscript/Inputs/insert-after.s
@@ -0,0 +1,11 @@
+.section .foo.text,"ax"
+.quad 0
+
+.section .foo.data,"aw"
+.quad 0
+
+.section .text.1,"ax"
+.quad 0
+
+.section .data.1,"aw"
+.quad 0
diff --git a/test/ELF/linkerscript/Inputs/insert-after.script b/test/ELF/linkerscript/Inputs/insert-after.script
new file mode 100644
index 0000000..cb95878
--- /dev/null
+++ b/test/ELF/linkerscript/Inputs/insert-after.script
@@ -0,0 +1,4 @@
+SECTIONS {
+  .text  : { *(.text.*) }
+  .data  : { *(.data.*) }
+}
diff --git a/test/ELF/linkerscript/Inputs/sections-va-overflow.s b/test/ELF/linkerscript/Inputs/sections-va-overflow.s
new file mode 100644
index 0000000..6bb0490
--- /dev/null
+++ b/test/ELF/linkerscript/Inputs/sections-va-overflow.s
@@ -0,0 +1,6 @@
+.global _start
+_start:
+  retq
+
+.bss
+.space 0x2000
diff --git a/test/ELF/linkerscript/bss-fill.s b/test/ELF/linkerscript/bss-fill.s
deleted file mode 100644
index 92f9fdf..0000000
--- a/test/ELF/linkerscript/bss-fill.s
+++ /dev/null
@@ -1,7 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
-# RUN: echo "SECTIONS { .bss : { . += 0x10000; *(.bss) } =0xFF };" > %t.script
-# RUN: ld.lld -o %t --script %t.script %t.o
-
-.section .bss,"",@nobits
-.short 0
diff --git a/test/ELF/linkerscript/bss-fill.test b/test/ELF/linkerscript/bss-fill.test
new file mode 100644
index 0000000..b7ed476
--- /dev/null
+++ b/test/ELF/linkerscript/bss-fill.test
@@ -0,0 +1,13 @@
+# REQUIRES: x86
+# RUN: echo '.section .bss,"",@nobits; .short 0' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
+# RUN: ld.lld -o %t --script %s %t.o
+
+## Check we do not crash.
+
+SECTIONS {
+ .bss : {
+   . += 0x10000;
+   *(.bss)
+ } =0xFF
+}
diff --git a/test/ELF/linkerscript/common-filespec.s b/test/ELF/linkerscript/common-filespec.test
similarity index 88%
rename from test/ELF/linkerscript/common-filespec.s
rename to test/ELF/linkerscript/common-filespec.test
index 25bb486..2afd91d 100644
--- a/test/ELF/linkerscript/common-filespec.s
+++ b/test/ELF/linkerscript/common-filespec.test
@@ -1,11 +1,17 @@
 # REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile0.o
+# RUN: echo '.long 0; .comm common_uniq_0,4,4; .comm common_multiple,8,8' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %tfile0.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec1.s -o %tfile1.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec2.s -o %tfile2.o
-# RUN: echo "SECTIONS { .common_0 : { *file0.o(COMMON) } .common_1 : { *file1.o(COMMON) } .common_2 : { *file2.o(COMMON) } }" > %t.script
-# RUN: ld.lld -o %t1 --script %t.script %tfile0.o %tfile1.o %tfile2.o
+# RUN: ld.lld -o %t1 --script %s %tfile0.o %tfile1.o %tfile2.o
 # RUN: llvm-readobj -s -t %t1 | FileCheck %s
 
+SECTIONS {
+  .common_0 : { *file0.o(COMMON) }
+  .common_1 : { *file1.o(COMMON) }
+  .common_2 : { *file2.o(COMMON) }
+}
+
 # Make sure all 3 sections are allocated and they have sizes and alignments
 # corresponding to the commons assigned to them
 # CHECK:       Section {
@@ -96,10 +102,3 @@
 # CHECK-NEXT:    Other: 0
 # CHECK-NEXT:    Section: .common_2
 # CHECK-NEXT:  }
-
-.globl _start
-_start:
-  jmp _start
-
-.comm common_uniq_0,4,4
-.comm common_multiple,8,8
diff --git a/test/ELF/linkerscript/constructor.s b/test/ELF/linkerscript/constructor.s
deleted file mode 100644
index acb86fd..0000000
--- a/test/ELF/linkerscript/constructor.s
+++ /dev/null
@@ -1,13 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
-# RUN: echo "SECTIONS { foo : { *(.foo) CONSTRUCTORS } }" > %t.script
-# RUN: ld.lld -o %t1 --script %t.script %t.o
-
-# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
-# CHECK:      Sections:
-# CHECK-NEXT: Idx Name          Size
-# CHECK-NEXT:   0               00000000
-# CHECK-NEXT:   1 foo           00000001
-
-.section foo, "a"
-.byte 0
diff --git a/test/ELF/linkerscript/constructor.test b/test/ELF/linkerscript/constructor.test
new file mode 100644
index 0000000..edd2cd2
--- /dev/null
+++ b/test/ELF/linkerscript/constructor.test
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+# RUN: echo '.section foo, "a"; .byte 0' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
+# RUN: ld.lld -o %t1 --script %s %t.o
+
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK:      Sections:
+# CHECK-NEXT: Idx Name          Size
+# CHECK-NEXT:   0               00000000
+# CHECK-NEXT:   1 foo           00000001
+
+SECTIONS {
+  foo : {
+    *(.foo)
+    CONSTRUCTORS
+  }
+}
diff --git a/test/ELF/linkerscript/discard-gnu-hash.s b/test/ELF/linkerscript/discard-gnu-hash.s
new file mode 100644
index 0000000..77f168d
--- /dev/null
+++ b/test/ELF/linkerscript/discard-gnu-hash.s
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: ld.lld --hash-style both -shared -o %t1 %t
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK: .gnu.hash
+# CHECK: .hash
+
+# RUN: echo "SECTIONS { /DISCARD/ : { *(.hash) } }" > %t.script
+# RUN: ld.lld --hash-style both -shared -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 \
+# RUN:   | FileCheck %s --check-prefix=HASH
+# HASH-NOT: .hash
+# HASH:     .gnu.hash
+# HASH-NOT: .hash
+
+# RUN: echo "SECTIONS { /DISCARD/ : { *(.gnu.hash) } }" > %t.script
+# RUN: ld.lld --hash-style both -shared -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 \
+# RUN:   | FileCheck %s --check-prefix=GNUHASH
+# GNUHASH-NOT: .gnu.hash
+# GNUHASH:     .hash
+# GNUHASH-NOT: .gnu.hash
diff --git a/test/ELF/linkerscript/discard-section-err.s b/test/ELF/linkerscript/discard-section-err.s
index 8ad5b48..f1d3b96 100644
--- a/test/ELF/linkerscript/discard-section-err.s
+++ b/test/ELF/linkerscript/discard-section-err.s
@@ -22,4 +22,14 @@
 # RUN:   FileCheck -check-prefix=DYNSTR %s
 # DYNSTR: discarding .dynstr section is not allowed
 
+# RUN: echo "SECTIONS { /DISCARD/ : { *(.rela.plt) } }" > %t.script
+# RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \
+# RUN:   FileCheck -check-prefix=RELAPLT %s
+# RELAPLT: discarding .rela.plt section is not allowed
+
+# RUN: echo "SECTIONS { /DISCARD/ : { *(.rela.dyn) } }" > %t.script
+# RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \
+# RUN:   FileCheck -check-prefix=RELADYN %s
+# RELADYN: discarding .rela.dyn section is not allowed
+
 .comm foo,4,4
diff --git a/test/ELF/linkerscript/double-bss.s b/test/ELF/linkerscript/double-bss.s
deleted file mode 100644
index c24332f..0000000
--- a/test/ELF/linkerscript/double-bss.s
+++ /dev/null
@@ -1,21 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; " > %t.script
-# RUN: echo ".text : { *(.text*) }" >> %t.script
-# RUN: echo ".bss1 : { *(.bss) }" >> %t.script
-# RUN: echo ".bss2 : { *(COMMON) }" >> %t.script
-# RUN: echo "}" >> %t.script
-
-# RUN: ld.lld -o %t1 --script %t.script %t
-# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
-# CHECK:      .bss1          00000004 0000000000000122 BSS
-# CHECK-NEXT: .bss2          00000080 0000000000000128 BSS
-
-.globl _start
-_start:
-  jmp _start
-
-.bss
-.zero 4
-
-.comm q,128,8
diff --git a/test/ELF/linkerscript/double-bss.test b/test/ELF/linkerscript/double-bss.test
new file mode 100644
index 0000000..32b796d
--- /dev/null
+++ b/test/ELF/linkerscript/double-bss.test
@@ -0,0 +1,14 @@
+# REQUIRES: x86
+# RUN: echo '.short 0; .bss; .zero 4; .comm q,128,8' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t
+# RUN: ld.lld -o %t1 --script %s %t
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK:      .bss1          00000004 0000000000000122 BSS
+# CHECK-NEXT: .bss2          00000080 0000000000000128 BSS
+
+SECTIONS {
+  . = SIZEOF_HEADERS;
+  .text : { *(.text*) }
+  .bss1 : { *(.bss) }
+  .bss2 : { *(COMMON) }
+}
diff --git a/test/ELF/linkerscript/eh-frame-emit-relocs.s b/test/ELF/linkerscript/eh-frame-emit-relocs.s
new file mode 100644
index 0000000..d951cbc
--- /dev/null
+++ b/test/ELF/linkerscript/eh-frame-emit-relocs.s
@@ -0,0 +1,13 @@
+# REQUIRES: x86
+# RUN: echo "SECTIONS { .foo : { *(.eh_frame) } }" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld --emit-relocs %t.o -T %t.script -o %t
+# RUN: llvm-objdump -section-headers %t | FileCheck %s
+
+# CHECK-NOT: eh_frame
+# CHECK:     .rela.foo
+# CHECK-NOT: eh_frame
+
+.text
+ .cfi_startproc
+ .cfi_endproc
diff --git a/test/ELF/linkerscript/empty-link-order.test b/test/ELF/linkerscript/empty-link-order.test
new file mode 100644
index 0000000..b63b60c
--- /dev/null
+++ b/test/ELF/linkerscript/empty-link-order.test
@@ -0,0 +1,21 @@
+# REQUIRES: arm
+# RUN: llvm-mc -filetype=obj -triple=arm-arm-none-eabi -o %t.o < /dev/null
+
+SECTIONS {
+  .foo : {
+    bar = .;
+    *(.ARM.exidx*)
+  }
+}
+
+# RUN: ld.lld %t.o -o %t --script %s
+
+## Check we do not crash and do not set SHF_LINK_ORDER flag for .foo
+# RUN: llvm-readobj -s %t | FileCheck %s
+# CHECK:      Section {
+# CHECK:       Index:
+# CHECK:       Name: .foo
+# CHECK-NEXT:  Type: SHT_ARM_EXIDX
+# CHECK-NEXT:  Flags [
+# CHECK-NEXT:    SHF_ALLOC
+# CHECK-NEXT:  ]
diff --git a/test/ELF/linkerscript/empty-tls.s b/test/ELF/linkerscript/empty-tls.s
deleted file mode 100644
index 0ef2e7b..0000000
--- a/test/ELF/linkerscript/empty-tls.s
+++ /dev/null
@@ -1,14 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: echo  "PHDRS { ph_tls PT_TLS; }" > %t.script
-# RUN: ld.lld -o %t.so -T %t.script %t.o -shared
-# RUN: llvm-readobj -l %t.so | FileCheck %s
-
-# test that we don't crash with an empty PT_TLS
-
-# CHECK:      Type: PT_TLS
-# CHECK-NEXT: Offset: 0x0
-# CHECK-NEXT: VirtualAddress: 0x0
-# CHECK-NEXT: PhysicalAddress: 0x0
-# CHECK-NEXT: FileSize: 0
-# CHECK-NEXT: MemSize: 0
diff --git a/test/ELF/linkerscript/empty-tls.test b/test/ELF/linkerscript/empty-tls.test
new file mode 100644
index 0000000..2f473cb
--- /dev/null
+++ b/test/ELF/linkerscript/empty-tls.test
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
+# RUN: ld.lld -o %t.so -T %s %t.o -shared
+# RUN: llvm-readobj -l %t.so | FileCheck %s
+
+PHDRS {
+  ph_tls PT_TLS;
+}
+
+# Test that we don't crash with an empty PT_TLS
+
+# CHECK:      Type: PT_TLS
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
diff --git a/test/ELF/linkerscript/exidx-crash.s b/test/ELF/linkerscript/exidx-crash.s
deleted file mode 100644
index c29d013..0000000
--- a/test/ELF/linkerscript/exidx-crash.s
+++ /dev/null
@@ -1,7 +0,0 @@
-# REQUIRES: aarch64
-
-# We used to crash on this.
-
-# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux
-# RUN: echo "SECTIONS { .ARM.exidx : { *(.foo) } }" > %t.script
-# RUN: ld.lld -T %t.script %t.o -o %t
diff --git a/test/ELF/linkerscript/exidx-crash.test b/test/ELF/linkerscript/exidx-crash.test
new file mode 100644
index 0000000..4d765f4
--- /dev/null
+++ b/test/ELF/linkerscript/exidx-crash.test
@@ -0,0 +1,10 @@
+# REQUIRES: aarch64
+
+# We used to crash on this.
+
+# RUN: llvm-mc /dev/null -o %t.o -filetype=obj -triple=aarch64-pc-linux
+# RUN: ld.lld -T %s %t.o -o %t
+
+SECTIONS {
+  .ARM.exidx : { *(.foo) }
+}
diff --git a/test/ELF/linkerscript/expr-invalid-sec.s b/test/ELF/linkerscript/expr-invalid-sec.s
deleted file mode 100644
index 5687751..0000000
--- a/test/ELF/linkerscript/expr-invalid-sec.s
+++ /dev/null
@@ -1,6 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
-# RUN: echo "SECTIONS { foo = ADDR(.text) + ADDR(.text); };" > %t.script
-# RUN: not ld.lld -o %t.so --script %t.script %t.o -shared 2>&1 | FileCheck %s
-
-# CHECK: error: {{.*}}.script:1: at least one side of the expression must be absolute
diff --git a/test/ELF/linkerscript/expr-invalid-sec.test b/test/ELF/linkerscript/expr-invalid-sec.test
new file mode 100644
index 0000000..946062a
--- /dev/null
+++ b/test/ELF/linkerscript/expr-invalid-sec.test
@@ -0,0 +1,9 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t.o
+# RUN: not ld.lld -o %t.so --script %s %t.o -shared 2>&1 | FileCheck %s
+
+# CHECK: error: {{.*}}.test:8: at least one side of the expression must be absolute
+
+SECTIONS {
+  foo = ADDR(.text) + ADDR(.text);
+};
diff --git a/test/ELF/linkerscript/header-addr.s b/test/ELF/linkerscript/header-addr.test
similarity index 73%
rename from test/ELF/linkerscript/header-addr.s
rename to test/ELF/linkerscript/header-addr.test
index 70e6f67..7994c0f 100644
--- a/test/ELF/linkerscript/header-addr.s
+++ b/test/ELF/linkerscript/header-addr.test
@@ -1,13 +1,15 @@
 # REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: echo "PHDRS {all PT_LOAD PHDRS;} \
-# RUN:       SECTIONS { \
-# RUN:       . = 0x2000 + SIZEOF_HEADERS; \
-# RUN:       .text : {*(.text)} :all \
-# RUN:     }" > %t.script
-# RUN: ld.lld --hash-style=sysv -o %t.so --script %t.script %t.o -shared
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
+# RUN: ld.lld --hash-style=sysv -o %t.so --script %s %t.o -shared
 # RUN: llvm-readobj -program-headers %t.so | FileCheck %s
 
+PHDRS { all PT_LOAD PHDRS; }
+
+SECTIONS {
+  . = 0x2000 + SIZEOF_HEADERS;
+  .text : {*(.text)} :all
+}
+
 # CHECK:      ProgramHeaders [
 # CHECK-NEXT:   ProgramHeader {
 # CHECK-NEXT:     Type: PT_LOAD
@@ -25,7 +27,7 @@
 # CHECK-NEXT:   }
 # CHECK-NEXT: ]
 
-# RUN: ld.lld --hash-style=sysv -o %t2.so --script %t.script %t.o -shared -z max-page-size=0x2000
+# RUN: ld.lld --hash-style=sysv -o %t2.so --script %s %t.o -shared -z max-page-size=0x2000
 # RUN: llvm-readobj -program-headers %t2.so \
 # RUN:   | FileCheck --check-prefix=MAXPAGE %s
 
diff --git a/test/ELF/linkerscript/header-phdr.s b/test/ELF/linkerscript/header-phdr.s
deleted file mode 100644
index 8c9097d..0000000
--- a/test/ELF/linkerscript/header-phdr.s
+++ /dev/null
@@ -1,13 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: echo "PHDRS { foobar PT_LOAD FILEHDR PHDRS; } \
-# RUN:       SECTIONS {  . = 0x1000;  .abc : { *(.zed) } : foobar }" > %t.script
-# RUN: ld.lld --script %t.script %t.o -o %t
-# RUN: llvm-readelf -l -S -W %t | FileCheck %s
-
-.section .zed, "a"
-.zero 4
-
-
-# CHECK: [ 1] .abc              PROGBITS        0000000000001000 001000 000004 00   A  0   0  1
-# CHECK: LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x001004 0x001004 R E 0x1000
diff --git a/test/ELF/linkerscript/header-phdr.test b/test/ELF/linkerscript/header-phdr.test
new file mode 100644
index 0000000..72be15b
--- /dev/null
+++ b/test/ELF/linkerscript/header-phdr.test
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+# RUN: echo '.section .zed, "a"; .zero 4' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
+# RUN: ld.lld --script %s %t.o -o %t
+# RUN: llvm-readelf -l -S -W %t | FileCheck %s
+
+# CHECK: [ 1] .abc              PROGBITS        0000000000001000 001000 000004 00   A  0   0  1
+# CHECK: LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x001004 0x001004 R E 0x1000
+
+PHDRS { foobar PT_LOAD FILEHDR PHDRS; }
+
+SECTIONS {
+  . = 0x1000;
+  .abc : { *(.zed) } : foobar
+}
diff --git a/test/ELF/linkerscript/huge-temporary-file.s b/test/ELF/linkerscript/huge-temporary-file.s
index d58709c..e30153c 100644
--- a/test/ELF/linkerscript/huge-temporary-file.s
+++ b/test/ELF/linkerscript/huge-temporary-file.s
@@ -3,7 +3,7 @@
 # RUN: echo "SECTIONS { .text 0x2000 : {. = 0x10 ; *(.text) } }" > %t.script
 # RUN: not ld.lld %t --script %t.script -o %t1
 
-## This inputs previously created a 4gb temporarily fine under 32 bit
+## This inputs previously created a 4gb temporarily file under 32 bit
 ## configuration. Issue was fixed. There is no clean way to check that from here.
 ## This testcase added for documentation purposes.
 
diff --git a/test/ELF/linkerscript/implicit-program-header.s b/test/ELF/linkerscript/implicit-program-header.s
deleted file mode 100644
index 682f202..0000000
--- a/test/ELF/linkerscript/implicit-program-header.s
+++ /dev/null
@@ -1,22 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: echo "PHDRS {                    \
-# RUN:   ph_write PT_LOAD FLAGS(2);     \
-# RUN:   ph_exec  PT_LOAD FLAGS(1);     \
-# RUN: }                                \
-# RUN: SECTIONS {                       \
-# RUN:  .bar : { *(.bar) } : ph_exec    \
-# RUN:  .foo : { *(.foo) }              \
-# RUN:  .text : { *(.text) } : ph_write \
-# RUN: }" > %t.script
-# RUN: ld.lld --hash-style=sysv -o %t1 --script %t.script  \
-# RUN:   %t.o -shared
-# RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s
-
-# CHECK:      Segment Sections...
-# CHECK-NEXT:   00     .text .dynsym .hash .dynstr .dynamic
-# CHECK-NEXT:   01     .bar .foo
-
-.quad 0
-.section .foo,"ax"
-.quad 0
diff --git a/test/ELF/linkerscript/implicit-program-header.test b/test/ELF/linkerscript/implicit-program-header.test
new file mode 100644
index 0000000..ea5c873
--- /dev/null
+++ b/test/ELF/linkerscript/implicit-program-header.test
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+
+# RUN: echo '.section .text,"ax"; .quad 0' > %t.s
+# RUN: echo '.section .foo,"ax"; .quad 0' >> %t.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t.s -o %t.o
+# RUN: ld.lld --hash-style=sysv -o %t1 --script %s  \
+# RUN:   %t.o -shared
+# RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s
+
+# CHECK:      Segment Sections...
+# CHECK-NEXT:   00     .text .dynsym .hash .dynstr .dynamic
+# CHECK-NEXT:   01     .bar .foo
+
+PHDRS {
+  ph_write PT_LOAD FLAGS(2);
+  ph_exec  PT_LOAD FLAGS(1);
+}
+
+SECTIONS {
+  .bar : { *(.bar) } : ph_exec
+  .foo : { *(.foo) }
+  .text : { *(.text) } : ph_write
+}
diff --git a/test/ELF/linkerscript/insert-after.test b/test/ELF/linkerscript/insert-after.test
new file mode 100644
index 0000000..ab5ba18
--- /dev/null
+++ b/test/ELF/linkerscript/insert-after.test
@@ -0,0 +1,29 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/insert-after.s -o %t1.o
+
+## Main linker script contains .text and .data sections. Here
+## we check that can use INSERT AFTER to insert sections .foo.data
+## and .foo.text at the right places.
+
+SECTIONS {
+  .foo.data : { *(.foo.data) }
+} INSERT AFTER .data;
+
+SECTIONS {
+  .foo.text : { *(.foo.text) }
+} INSERT AFTER .text;
+
+# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK:      Sections:
+# CHECK-NEXT: Idx Name          Size      Address          Type
+# CHECK-NEXT:   0               00000000 0000000000000000
+# CHECK-NEXT:   1 .text         00000008 0000000000000000 TEXT DATA
+# CHECK-NEXT:   2 .foo.text     00000008 0000000000000008 TEXT DATA
+# CHECK-NEXT:   3 .data         00000008 0000000000000010 DATA
+# CHECK-NEXT:   4 .foo.data     00000008 0000000000000018 DATA
+
+# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=ERR
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .text: section not defined
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .data: section not defined
diff --git a/test/ELF/linkerscript/insert-before.test b/test/ELF/linkerscript/insert-before.test
new file mode 100644
index 0000000..507e8bd
--- /dev/null
+++ b/test/ELF/linkerscript/insert-before.test
@@ -0,0 +1,29 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/insert-after.s -o %t1.o
+
+## Main linker script contains .text and .data sections. Here
+## we check that can use INSERT BEFORE to insert sections .foo.data
+## and .foo.text at the right places.
+
+SECTIONS {
+  .foo.data : { *(.foo.data) }
+} INSERT BEFORE .data;
+
+SECTIONS {
+  .foo.text : { *(.foo.text) }
+} INSERT BEFORE .text;
+
+# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK:      Sections:
+# CHECK-NEXT: Idx Name          Size      Address          Type
+# CHECK-NEXT:   0               00000000 0000000000000000
+# CHECK-NEXT:   1 .foo.text     00000008 0000000000000000 TEXT DATA
+# CHECK-NEXT:   2 .text         00000008 0000000000000008 TEXT DATA
+# CHECK-NEXT:   3 .foo.data     00000008 0000000000000010 DATA
+# CHECK-NEXT:   4 .data         00000008 0000000000000018 DATA
+
+# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=ERR
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .text: section not defined
+# ERR-DAG: error: unable to INSERT AFTER/BEFORE .data: section not defined
diff --git a/test/ELF/linkerscript/insert-broken.test b/test/ELF/linkerscript/insert-broken.test
new file mode 100644
index 0000000..9a29562
--- /dev/null
+++ b/test/ELF/linkerscript/insert-broken.test
@@ -0,0 +1,6 @@
+SECTIONS {
+  .foo : { *(.bar) }
+} INSERT .data;
+
+# RUN: not ld.lld -o %t1 --script %s 2>&1 | FileCheck %s
+# CHECK: {{.*}}:3: expected AFTER/BEFORE, but got '.data'
diff --git a/test/ELF/linkerscript/lazy-symbols.s b/test/ELF/linkerscript/lazy-symbols.test
similarity index 68%
rename from test/ELF/linkerscript/lazy-symbols.s
rename to test/ELF/linkerscript/lazy-symbols.test
index 22dffee..579df93 100644
--- a/test/ELF/linkerscript/lazy-symbols.s
+++ b/test/ELF/linkerscript/lazy-symbols.test
@@ -1,11 +1,12 @@
 # REQUIRES: x86
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/lazy-symbols.s -o %t1
 # RUN: llvm-ar rcs %tar %t1
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
-# RUN: echo "foo = 1;" > %t.script
-# RUN: ld.lld %t2 %tar --script %t.script -o %tout
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t2
+# RUN: ld.lld %t2 %tar --script %s -o %tout
 # RUN: llvm-readobj -symbols %tout | FileCheck %s
 
+foo = 1;
+
 # This test is to ensure a linker script can define a symbol which have the same
 # name as a lazy symbol.
 
diff --git a/test/ELF/linkerscript/lma-overflow.test b/test/ELF/linkerscript/lma-overflow.test
new file mode 100644
index 0000000..e572c05
--- /dev/null
+++ b/test/ELF/linkerscript/lma-overflow.test
@@ -0,0 +1,16 @@
+# REQUIRES: x86
+
+# RUN: echo '.section .foo,"a"; .quad 1' | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
+# RUN: not ld.lld -o %t %t.o --script %s 2>&1 | FileCheck %s
+# CHECK: error: section '.foo' will not fit in region 'flash': overflowed by 264 bytes
+
+MEMORY {
+  ram (rwx) : org = 0x1000, len = 0x300
+  flash (rwx) : org = 0x1000, len = 0x100
+}
+SECTIONS {
+  .foo : {
+    *(.foo)
+    . += 0x200;
+  } > ram AT>flash
+}
diff --git a/test/ELF/linkerscript/locationcountererr.s b/test/ELF/linkerscript/locationcountererr.s
deleted file mode 100644
index 113e102..0000000
--- a/test/ELF/linkerscript/locationcountererr.s
+++ /dev/null
@@ -1,11 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-
-# RUN: echo "SECTIONS {" > %t.script
-# RUN: echo ".text 0x2000 : {. = 0x10 ; *(.text) } }" >> %t.script
-# RUN: not ld.lld %t --script %t.script -o %t1 2>&1 | FileCheck %s
-# CHECK: {{.*}}.script:2: unable to move location counter backward for: .text
-
-.globl _start
-_start:
-nop
diff --git a/test/ELF/linkerscript/locationcountererr.test b/test/ELF/linkerscript/locationcountererr.test
new file mode 100644
index 0000000..6a1b213
--- /dev/null
+++ b/test/ELF/linkerscript/locationcountererr.test
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t
+# RUN: not ld.lld %t --script %s -o %t1 2>&1 | FileCheck %s
+# CHECK: {{.*}}.test:8: unable to move location counter backward for: .text
+
+SECTIONS {
+  .text 0x2000 : {
+    . = 0x10;
+    *(.text)
+  }
+}
diff --git a/test/ELF/linkerscript/map-file.test b/test/ELF/linkerscript/map-file.test
new file mode 100644
index 0000000..5ab3d01
--- /dev/null
+++ b/test/ELF/linkerscript/map-file.test
@@ -0,0 +1,37 @@
+# REQUIRES: x86
+
+# RUN: echo '.section .foo.1, "a"; .quad 1' > %t.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o
+
+# RUN: ld.lld -o %t %t.o -Map=%t.map --script %s
+# RUN: FileCheck -strict-whitespace %s < %t.map
+
+SECTIONS {
+  . = 0x1000;
+  .foo : {
+    BYTE(0x11)
+    SHORT(0x1122)
+    LONG(0x11223344)
+    QUAD(0x1122334455667788)
+    . += 0x1000;
+    *(.foo.1)
+    . += 0x123 *
+         (1 + 1);
+    foo = .;
+    bar = 0x42 - 0x26;
+  }
+}
+
+# CHECK:      Address          Size             Align Out     In      Symbol
+# CHECK-NEXT: 0000000000001000 000000000000125d     1 .foo
+# CHECK-NEXT: 0000000000001000 0000000000000001     1         BYTE ( 0x11 )
+# CHECK-NEXT: 0000000000001001 0000000000000002     1         SHORT ( 0x1122 )
+# CHECK-NEXT: 0000000000001003 0000000000000004     1         LONG ( 0x11223344 )
+# CHECK-NEXT: 0000000000001007 0000000000000008     1         QUAD ( 0x1122334455667788 )
+# CHECK-NEXT: 000000000000100f 0000000000001000     1         . += 0x1000
+# CHECK-NEXT: 000000000000200f 0000000000000008     1         {{.*}}{{/|\\}}map-file.test.tmp.o:(.foo.1)
+# CHECK-NEXT: 0000000000002017 0000000000000246     1         . += 0x123 * ( 1 + 1 )
+# CHECK-NEXT: 000000000000225d 0000000000000000     1         foo = .
+# CHECK-NEXT: 000000000000225d 0000000000000000     1         bar = 0x42 - 0x26
+# CHECK-NEXT: 0000000000002260 0000000000000000     4 .text
+# CHECK-NEXT: 0000000000002260 0000000000000000     4         {{.*}}{{/|\\}}map-file.test.tmp.o:(.text)
diff --git a/test/ELF/linkerscript/memory-at.s b/test/ELF/linkerscript/memory-at.s
deleted file mode 100644
index 9e56dbd..0000000
--- a/test/ELF/linkerscript/memory-at.s
+++ /dev/null
@@ -1,46 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-# RUN: echo "MEMORY {                                   \
-# RUN:   FLASH (rx) : ORIGIN = 0x1000, LENGTH = 0x100   \
-# RUN:   RAM (rwx)  : ORIGIN = 0x2000, LENGTH = 0x100 } \
-# RUN: SECTIONS {                                       \
-# RUN:  .text : { *(.text*) } > FLASH                   \
-# RUN:  __etext = .;                                    \
-# RUN:  .data : AT (__etext) { *(.data*) } > RAM        \
-# RUN: }" > %t.script
-# RUN: ld.lld %t --script %t.script -o %t2
-# RUN: llvm-readobj -program-headers %t2 | FileCheck %s
-
-# CHECK:      ProgramHeaders [
-# CHECK-NEXT:   ProgramHeader {
-# CHECK-NEXT:     Type: PT_LOAD
-# CHECK-NEXT:     Offset: 0x1000
-# CHECK-NEXT:     VirtualAddress: 0x1000
-# CHECK-NEXT:     PhysicalAddress: 0x1000
-# CHECK-NEXT:     FileSize: 8
-# CHECK-NEXT:     MemSize: 8
-# CHECK-NEXT:     Flags [
-# CHECK-NEXT:       PF_R
-# CHECK-NEXT:       PF_X
-# CHECK-NEXT:     ]
-# CHECK-NEXT:     Alignment:
-# CHECK-NEXT:   }
-# CHECK-NEXT:   ProgramHeader {
-# CHECK-NEXT:     Type: PT_LOAD
-# CHECK-NEXT:     Offset: 0x2000
-# CHECK-NEXT:     VirtualAddress: 0x2000
-# CHECK-NEXT:     PhysicalAddress: 0x1008
-# CHECK-NEXT:     FileSize: 8
-# CHECK-NEXT:     MemSize: 8
-# CHECK-NEXT:     Flags [
-# CHECK-NEXT:       PF_R
-# CHECK-NEXT:       PF_W
-# CHECK-NEXT:     ]
-# CHECK-NEXT:     Alignment:
-# CHECK-NEXT:   }
-
-.section .text, "ax"
-.quad 0
-
-.section .data, "aw"
-.quad 0
diff --git a/test/ELF/linkerscript/memory-at.test b/test/ELF/linkerscript/memory-at.test
new file mode 100644
index 0000000..0f06a66
--- /dev/null
+++ b/test/ELF/linkerscript/memory-at.test
@@ -0,0 +1,45 @@
+# REQUIRES: x86
+# RUN: echo '.section .text,"ax"; .quad 0' > %t.s
+# RUN: echo '.section .data,"aw"; .quad 0' >> %t.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t
+# RUN: ld.lld %t --script %s -o %t2
+# RUN: llvm-readobj -program-headers %t2 | FileCheck %s
+
+MEMORY {
+  FLASH (rx) : ORIGIN = 0x1000, LENGTH = 0x100
+  RAM (rwx)  : ORIGIN = 0x2000, LENGTH = 0x100
+}
+
+SECTIONS {
+ .text : { *(.text*) } > FLASH
+ __etext = .;
+ .data : AT (__etext) { *(.data*) } > RAM
+}
+
+# CHECK:      ProgramHeaders [
+# CHECK-NEXT:   ProgramHeader {
+# CHECK-NEXT:     Type: PT_LOAD
+# CHECK-NEXT:     Offset: 0x1000
+# CHECK-NEXT:     VirtualAddress: 0x1000
+# CHECK-NEXT:     PhysicalAddress: 0x1000
+# CHECK-NEXT:     FileSize: 8
+# CHECK-NEXT:     MemSize: 8
+# CHECK-NEXT:     Flags [
+# CHECK-NEXT:       PF_R
+# CHECK-NEXT:       PF_X
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Alignment:
+# CHECK-NEXT:   }
+# CHECK-NEXT:   ProgramHeader {
+# CHECK-NEXT:     Type: PT_LOAD
+# CHECK-NEXT:     Offset: 0x2000
+# CHECK-NEXT:     VirtualAddress: 0x2000
+# CHECK-NEXT:     PhysicalAddress: 0x1008
+# CHECK-NEXT:     FileSize: 8
+# CHECK-NEXT:     MemSize: 8
+# CHECK-NEXT:     Flags [
+# CHECK-NEXT:       PF_R
+# CHECK-NEXT:       PF_W
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Alignment:
+# CHECK-NEXT:   }
diff --git a/test/ELF/linkerscript/memory-region-alignment.test b/test/ELF/linkerscript/memory-region-alignment.test
new file mode 100644
index 0000000..ba9d4e3
--- /dev/null
+++ b/test/ELF/linkerscript/memory-region-alignment.test
@@ -0,0 +1,58 @@
+# REQUIRES: x86
+# RUN: echo '.section .foo,"a"; .quad 0; .section .zed,"M",@progbits,1; .byte 0' > %t.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o
+
+MEMORY {
+  ram (rwx): org = 0x1, len = 96K
+}
+
+SECTIONS {
+  .foo : ALIGN(8) {
+    *(.foo)
+  } > ram
+  
+  .zed : {
+    *(.zed)
+  } > ram
+}
+
+# RUN: ld.lld %t.o -o %t --script %s
+# RUN: llvm-readobj -sections %t | FileCheck %s
+
+# CHECK:        Name: .foo
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x8
+# CHECK-NEXT:   Offset: 0x1008
+# CHECK-NEXT:   Size: 8
+
+# CHECK:        Name: .text
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:     SHF_EXECINSTR
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x10
+# CHECK-NEXT:   Offset: 0x1010
+# CHECK-NEXT:   Size: 0
+
+# CHECK:        Name: .zed
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_MERGE
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x10
+# CHECK-NEXT:   Offset: 0x1010
+# CHECK-NEXT:   Size: 1
+
+# CHECK:        Name: .comment
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_MERGE
+# CHECK-NEXT:     SHF_STRINGS
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x0
+# CHECK-NEXT:   Offset: 0x1011
+# CHECK-NEXT:   Size: 8
diff --git a/test/ELF/linkerscript/no-pt-load.s b/test/ELF/linkerscript/no-pt-load.s
deleted file mode 100644
index c704025..0000000
--- a/test/ELF/linkerscript/no-pt-load.s
+++ /dev/null
@@ -1,5 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: echo "PHDRS {foo PT_DYNAMIC ;} " \
-# RUN:      "SECTIONS { .text : { *(.text) } : foo }" > %t.script
-# RUN: ld.lld -o %t1 --script %t.script %t.o
diff --git a/test/ELF/linkerscript/no-pt-load.test b/test/ELF/linkerscript/no-pt-load.test
new file mode 100644
index 0000000..16f7f44
--- /dev/null
+++ b/test/ELF/linkerscript/no-pt-load.test
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
+# RUN: ld.lld -o %t1 --script %s %t.o
+
+## Check we do not crash.
+
+PHDRS { foo PT_DYNAMIC; }
+
+SECTIONS {
+  .text : { *(.text) } : foo
+}
diff --git a/test/ELF/linkerscript/non-absolute2.s b/test/ELF/linkerscript/non-absolute2.test
similarity index 64%
rename from test/ELF/linkerscript/non-absolute2.s
rename to test/ELF/linkerscript/non-absolute2.test
index 97c34d3..fa9e0e4 100644
--- a/test/ELF/linkerscript/non-absolute2.s
+++ b/test/ELF/linkerscript/non-absolute2.test
@@ -1,9 +1,13 @@
 # REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
-# RUN: echo "SECTIONS { A = . + 0x1; . += 0x1000; }" > %t.script
-# RUN: ld.lld -shared %t1.o --script %t.script -o %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t1.o
+# RUN: ld.lld -shared %t1.o --script %s -o %t
 # RUN: llvm-objdump -section-headers -t %t | FileCheck %s
 
+SECTIONS {
+  A = . + 0x1;
+  . += 0x1000;
+}
+
 # CHECK:       Sections:
 # CHECK-NEXT:   Idx Name          Size      Address
 # CHECK-NEXT:    0               00000000 0000000000000000
diff --git a/test/ELF/linkerscript/openbsd-bootdata.s b/test/ELF/linkerscript/openbsd-bootdata.s
deleted file mode 100644
index 3e90574..0000000
--- a/test/ELF/linkerscript/openbsd-bootdata.s
+++ /dev/null
@@ -1,7 +0,0 @@
-# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
-# RUN: echo "PHDRS { boot PT_OPENBSD_BOOTDATA; }" > %t.script
-# RUN: ld.lld --script %t.script %t.o -o %t
-# RUN: llvm-readobj --program-headers -s %t | FileCheck %s
-
-# CHECK:      ProgramHeader {
-# CHECK:        Type: PT_OPENBSD_BOOTDATA (0x65A41BE6)
diff --git a/test/ELF/linkerscript/openbsd-bootdata.test b/test/ELF/linkerscript/openbsd-bootdata.test
new file mode 100644
index 0000000..ad3a569
--- /dev/null
+++ b/test/ELF/linkerscript/openbsd-bootdata.test
@@ -0,0 +1,8 @@
+# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux /dev/null -o %t.o
+# RUN: ld.lld --script %s %t.o -o %t
+# RUN: llvm-readobj --program-headers -s %t | FileCheck %s
+
+PHDRS { boot PT_OPENBSD_BOOTDATA; }
+
+# CHECK:      ProgramHeader {
+# CHECK:        Type: PT_OPENBSD_BOOTDATA (0x65A41BE6)
diff --git a/test/ELF/linkerscript/openbsd-wxneeded.s b/test/ELF/linkerscript/openbsd-wxneeded.test
similarity index 65%
rename from test/ELF/linkerscript/openbsd-wxneeded.s
rename to test/ELF/linkerscript/openbsd-wxneeded.test
index d371da9..3b82a94 100644
--- a/test/ELF/linkerscript/openbsd-wxneeded.s
+++ b/test/ELF/linkerscript/openbsd-wxneeded.test
@@ -1,8 +1,9 @@
-# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
-# RUN: echo "PHDRS { text PT_LOAD FILEHDR PHDRS; wxneeded PT_OPENBSD_WXNEEDED; }" > %t.script
-# RUN: ld.lld -z wxneeded --script %t.script %t.o -o %t
+# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux /dev/null -o %t.o
+# RUN: ld.lld -z wxneeded --script %s %t.o -o %t
 # RUN: llvm-readobj --program-headers %t | FileCheck %s
 
+PHDRS { text PT_LOAD FILEHDR PHDRS; wxneeded PT_OPENBSD_WXNEEDED; }
+
 # CHECK:      ProgramHeader {
 # CHECK:        Type: PT_OPENBSD_WXNEEDED (0x65A3DBE7)
 # CHECK-NEXT:   Offset: 0x0
diff --git a/test/ELF/linkerscript/operators.test b/test/ELF/linkerscript/operators.test
index fa6e7ee..7996044 100644
--- a/test/ELF/linkerscript/operators.test
+++ b/test/ELF/linkerscript/operators.test
@@ -26,6 +26,8 @@
   unary = -1 + 3;
   lshift = 1 << 5;
   rshift = 0xff >> 3;
+  precedence1 = 1 | 0xff & 1 << 1 + 1 * 2;
+  precedence2 = (1 | (0xff & (1 << (1 + (1 * 2)))));
   maxpagesize = CONSTANT (MAXPAGESIZE);
   commonpagesize = CONSTANT (COMMONPAGESIZE);
   . = 0xfff0;
@@ -34,6 +36,8 @@
   _end = .;
   minus_rel = _end - 0x10;
   minus_abs = _end - _start;
+  max = MAX(11, 22);
+  min = MIN(11, 22);
 }
 
 # CHECK: 00000000000006 *ABS* 00000000 plus
@@ -56,12 +60,16 @@
 # CHECK: 00000000000002 *ABS* 00000000 unary
 # CHECK: 00000000000020 *ABS* 00000000 lshift
 # CHECK: 0000000000001f *ABS* 00000000 rshift
+# CHECK: 00000000000009 *ABS* 00000000 precedence1
+# CHECK: 00000000000009 *ABS* 00000000 precedence2
 # CHECK: 00000000001000 *ABS* 00000000 maxpagesize
 # CHECK: 00000000001000 *ABS* 00000000 commonpagesize
 # CHECK: 0000000000ffff *ABS* 00000000 datasegmentalign
 # CHECK: 0000000000fff0 *ABS* 00000000 datasegmentalign2
 # CHECK: 0000000000ffe0 .text 00000000 minus_rel
 # CHECK: 0000000000fff0 *ABS* 00000000 minus_abs
+# CHECK: 00000000000016 *ABS* 00000000 max
+# CHECK: 0000000000000b *ABS* 00000000 min
 
 ## Mailformed number error.
 # RUN: echo "SECTIONS { . = 0x12Q41; }" > %t.script
diff --git a/test/ELF/linkerscript/orphan-first-cmd.s b/test/ELF/linkerscript/orphan-first-cmd.s
deleted file mode 100644
index 263cb30..0000000
--- a/test/ELF/linkerscript/orphan-first-cmd.s
+++ /dev/null
@@ -1,20 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: echo "SECTIONS { \
-# RUN:         foo = 123; \
-# RUN:         . = 0x1000; \
-# RUN:         . = 0x2000; \
-# RUN:         .bar : { *(.bar) } \
-# RUN:       }" > %t.script
-# RUN: ld.lld -o %t -T %t.script %t.o -shared
-# RUN: llvm-readobj -s %t | FileCheck %s
-
-# CHECK:      Name: .text
-# CHECK-NEXT: Type: SHT_PROGBITS
-# CHECK-NEXT: Flags [
-# CHECK-NEXT:   SHF_ALLOC
-# CHECK-NEXT:   SHF_EXECINSTR
-# CHECK-NEXT: ]
-# CHECK-NEXT: Address: 0x1000
-
-.section .bar, "aw"
diff --git a/test/ELF/linkerscript/orphan-first-cmd.test b/test/ELF/linkerscript/orphan-first-cmd.test
new file mode 100644
index 0000000..6ef473b
--- /dev/null
+++ b/test/ELF/linkerscript/orphan-first-cmd.test
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+# RUN: echo '.section .bar, "aw"' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
+# RUN: ld.lld -o %t -T %s %t.o -shared
+# RUN: llvm-readobj -s %t | FileCheck %s
+
+SECTIONS {
+  foo = 123;
+  . = 0x1000;
+  . = 0x2000;
+  .bar : { *(.bar) }
+}
+
+# CHECK:      Name: .text
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT:   SHF_ALLOC
+# CHECK-NEXT:   SHF_EXECINSTR
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x1000
diff --git a/test/ELF/linkerscript/outputarch.s b/test/ELF/linkerscript/outputarch.s
deleted file mode 100644
index dd3bf93..0000000
--- a/test/ELF/linkerscript/outputarch.s
+++ /dev/null
@@ -1,4 +0,0 @@
-# REQUIRES: x86
-# RUN: echo "OUTPUT_ARCH(All data written here is ignored)" > %t.script
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1
-# RUN: ld.lld -shared -o %t2 %t1 %t.script
diff --git a/test/ELF/linkerscript/outputarch.test b/test/ELF/linkerscript/outputarch.test
new file mode 100644
index 0000000..4819a98
--- /dev/null
+++ b/test/ELF/linkerscript/outputarch.test
@@ -0,0 +1,5 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd /dev/null -o %t1
+# RUN: ld.lld -shared -o %t2 %t1 %s
+
+OUTPUT_ARCH(All data written here is ignored)
diff --git a/test/ELF/linkerscript/overlapping-sections.s b/test/ELF/linkerscript/overlapping-sections.s
index fcc9957..0b7b741 100644
--- a/test/ELF/linkerscript/overlapping-sections.s
+++ b/test/ELF/linkerscript/overlapping-sections.s
@@ -1,61 +1,5 @@
-# TODO: maybe this should be converted to an x86 test to get more buildbot coverage
-# REQUIRES: mips
-# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
-
-# RUN: echo "SECTIONS { \
-# RUN:   .sec1 0x8000 : { sec1_start = .; *(.first_sec) sec1_end = .;} \
-# RUN:   .sec2 0x8800 : { sec2_start = .; *(.second_sec) sec2_end = .;} \
-# RUN: }" > %t.script
-# RUN: ld.lld -o %t.so --script %t.script %t.o -shared
-# RUN: llvm-readobj -sections -program-headers %t.so | FileCheck %s -check-prefix GOOD
-
-# GOOD:        Name: .sec1
-# GOOD-NEXT:   Type: SHT_PROGBITS (0x1)
-# GOOD-NEXT:   Flags [ (0x3)
-# GOOD-NEXT:     SHF_ALLOC (0x2)
-# GOOD-NEXT:     SHF_WRITE (0x1)
-# GOOD-NEXT:   ]
-# GOOD-NEXT:   Address: 0x8000
-# GOOD-NEXT:   Offset: 0x18000
-# GOOD-NEXT:   Size: 256
-
-# GOOD:        Name: .sec2
-# GOOD-NEXT:   Type: SHT_PROGBITS (0x1)
-# GOOD-NEXT:   Flags [ (0x3)
-# GOOD-NEXT:     SHF_ALLOC (0x2)
-# GOOD-NEXT:     SHF_WRITE (0x1)
-# GOOD-NEXT:   ]
-# GOOD-NEXT:   Address: 0x8800
-# GOOD-NEXT:   Offset: 0x18800
-# GOOD-NEXT:   Size: 256
-
-# GOOD:      ProgramHeaders [
-# GOOD-NEXT:  ProgramHeader {
-# GOOD-NEXT:    Type: PT_LOAD (0x1)
-# GOOD-NEXT:    Offset: 0x10000
-# GOOD-NEXT:    VirtualAddress: 0x0
-# GOOD-NEXT:    PhysicalAddress: 0x0
-# GOOD-NEXT:    FileSize: 481
-# GOOD-NEXT:    MemSize: 481
-# GOOD-NEXT:    Flags [ (0x5)
-# GOOD-NEXT:      PF_R (0x4)
-# GOOD-NEXT:      PF_X (0x1)
-# GOOD-NEXT:    ]
-# GOOD-NEXT:    Alignment: 65536
-# GOOD-NEXT:  }
-# GOOD-NEXT:  ProgramHeader {
-# GOOD-NEXT:    Type: PT_LOAD (0x1)
-# GOOD-NEXT:    Offset: 0x18000
-# GOOD-NEXT:    VirtualAddress: 0x8000
-# GOOD-NEXT:    PhysicalAddress: 0x8000
-# GOOD-NEXT:    FileSize: 2320
-# GOOD-NEXT:    MemSize: 2320
-# GOOD-NEXT:    Flags [ (0x6)
-# GOOD-NEXT:      PF_R (0x4)
-# GOOD-NEXT:      PF_W (0x2)
-# GOOD-NEXT:    ]
-# GOOD-NEXT:    Alignment: 65536
-# GOOD-NEXT:  }
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 
 # RUN: echo "SECTIONS { \
 # RUN:   .sec1 0x8000 : AT(0x8000) { sec1_start = .; *(.first_sec) sec1_end = .;} \
@@ -63,8 +7,8 @@
 # RUN: }" > %t-lma.script
 # RUN: not ld.lld -o %t.so --script %t-lma.script %t.o -shared 2>&1 | FileCheck %s -check-prefix LMA-OVERLAP-ERR
 # LMA-OVERLAP-ERR:      error: section .sec1 load address range overlaps with .sec2
-# LMA-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000 -> 0x80FF]
-# LMA-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8080 -> 0x817F]
+# LMA-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000, 0x80FF]
+# LMA-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8080, 0x817F]
 
 # Check that we create the expected binary with --noinhibit-exec or --no-check-sections:
 # RUN: ld.lld -o %t.so --script %t-lma.script %t.o -shared --noinhibit-exec
@@ -75,17 +19,16 @@
 # overlaps with where .sec1 is loaded:
 # RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t.so | FileCheck %s -check-prefix BAD-LMA
 # BAD-LMA-LABEL: Section Headers:
-# BAD-LMA: .sec1             PROGBITS        0000000000008000 018000 000100 00  WA  0   0  1
-# BAD-LMA: .sec2             PROGBITS        0000000000008800 018800 000100 00  WA  0   0  1
+# BAD-LMA: .sec1             PROGBITS        0000000000008000 002000 000100 00  WA  0   0  1
+# BAD-LMA: .sec2             PROGBITS        0000000000008800 002800 000100 00  WA  0   0  1
 # BAD-LMA-LABEL: Program Headers:
 # BAD-LMA-NEXT:  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
-# BAD-LMA-NEXT:  LOAD           0x010000 0x0000000000000000 0x0000000000000000 0x0001e1 0x0001e1 R E 0x10000
-# BAD-LMA-NEXT:  LOAD           0x018000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW  0x10000
-# BAD-LMA-NEXT:  LOAD           0x018800 0x0000000000008800 0x0000000000008080 0x000110 0x000110 RW  0x10000
+# BAD-LMA-NEXT:  LOAD           0x001000 0x0000000000000000 0x0000000000000000 0x0000fd 0x0000fd R E 0x1000
+# BAD-LMA-NEXT:  LOAD           0x002000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW  0x1000
+# BAD-LMA-NEXT:  LOAD           0x002800 0x0000000000008800 0x0000000000008080 0x000170 0x000170 RW  0x1000
 # BAD-LMA-LABEL: Section to Segment mapping:
 # BAD-LMA:  01     .sec1
-# BAD-LMA:  02     .sec2 .data .got
-
+# BAD-LMA:  02     .sec2 .dynamic
 
 # Now try a script where the virtual memory addresses overlap but ensure that the
 # load addresses don't:
@@ -95,23 +38,23 @@
 # RUN: }" > %t-vaddr.script
 # RUN: not ld.lld -o %t.so --script %t-vaddr.script %t.o -shared 2>&1 | FileCheck %s -check-prefix VADDR-OVERLAP-ERR
 # VADDR-OVERLAP-ERR:      error: section .sec1 virtual address range overlaps with .sec2
-# VADDR-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000 -> 0x80FF]
-# VADDR-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8020 -> 0x811F]
+# VADDR-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000, 0x80FF]
+# VADDR-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8020, 0x811F]
 
 # Check that the expected binary was created with --noinhibit-exec:
 # RUN: ld.lld -o %t.so --script %t-vaddr.script %t.o -shared --noinhibit-exec
 # RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t.so | FileCheck %s -check-prefix BAD-VADDR
 # BAD-VADDR-LABEL: Section Headers:
-# BAD-VADDR: .sec1             PROGBITS        0000000000008000 018000 000100 00  WA  0   0  1
-# BAD-VADDR: .sec2             PROGBITS        0000000000008020 028020 000100 00  WA  0   0  1
+# BAD-VADDR: .sec1             PROGBITS        0000000000008000 002000 000100 00  WA  0   0  1
+# BAD-VADDR: .sec2             PROGBITS        0000000000008020 003020 000100 00  WA  0   0  1
 # BAD-VADDR-LABEL: Program Headers:
 # BAD-VADDR-NEXT:  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
-# BAD-VADDR-NEXT:  LOAD           0x010000 0x0000000000000000 0x0000000000000000 0x0001e1 0x0001e1 R E 0x10000
-# BAD-VADDR-NEXT:  LOAD           0x018000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW  0x10000
-# BAD-VADDR-NEXT:  LOAD           0x028020 0x0000000000008020 0x0000000000008800 0x000110 0x000110 RW  0x10000
+# BAD-VADDR-NEXT:  LOAD           0x001000 0x0000000000000000 0x0000000000000000 0x0000fd 0x0000fd R E 0x1000
+# BAD-VADDR-NEXT:  LOAD           0x002000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW  0x1000
+# BAD-VADDR-NEXT:  LOAD           0x003020 0x0000000000008020 0x0000000000008800 0x000170 0x000170 RW  0x1000
 # BAD-VADDR-LABEL: Section to Segment mapping:
 # BAD-VADDR:  01     .sec1
-# BAD-VADDR:  02     .sec2 .data .got
+# BAD-VADDR:  02     .sec2 .dynamic
 
 # Finally check the case where both LMA and vaddr overlap
 
@@ -123,17 +66,17 @@
 # RUN: not ld.lld -o %t.so --script %t-both-overlap.script %t.o -shared 2>&1 | FileCheck %s -check-prefix BOTH-OVERLAP-ERR
 
 # BOTH-OVERLAP-ERR:      error: section .sec1 file range overlaps with .sec2
-# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x18000 -> 0x180FF]
-# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x18040 -> 0x1813F]
+# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x2000, 0x20FF]
+# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x2040, 0x213F]
 # BOTH-OVERLAP-ERR:      error: section .sec1 virtual address range overlaps with .sec2
-# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000 -> 0x80FF]
-# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8040 -> 0x813F]
+# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000, 0x80FF]
+# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8040, 0x813F]
 # BOTH-OVERLAP-ERR:      error: section .sec1 load address range overlaps with .sec2
-# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000 -> 0x80FF]
-# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8040 -> 0x813F]
+# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000, 0x80FF]
+# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8040, 0x813F]
 
 # RUN: ld.lld -o %t.so --script %t-both-overlap.script %t.o -shared --noinhibit-exec
-# Note: I case everything overlaps we create a binary with overlapping file
+# Note: In case everything overlaps we create a binary with overlapping file
 # offsets. ld.bfd seems to place .sec1 to file offset 18000 and .sec2
 # at 18100 so that only virtual addr and LMA overlap
 # However, in order to create such a broken binary the user has to ignore a
@@ -141,24 +84,23 @@
 
 # RUN: llvm-objdump -s %t.so | FileCheck %s -check-prefix BROKEN-OUTPUT-FILE
 # BROKEN-OUTPUT-FILE-LABEL: Contents of section .sec1:
-# BROKEN-OUTPUT-FILE-NEXT: 8000 01010101 01010101 01010101 01010101  ................
-# BROKEN-OUTPUT-FILE-NEXT: 8010 01010101 01010101 01010101 01010101  ................
-# BROKEN-OUTPUT-FILE-NEXT: 8020 01010101 01010101 01010101 01010101  ................
-# BROKEN-OUTPUT-FILE-NEXT: 8030 01010101 01010101 01010101 01010101  ................
+# BROKEN-OUTPUT-FILE-NEXT: 8000 01010101 01010101 01010101 01010101
+# BROKEN-OUTPUT-FILE-NEXT: 8010 01010101 01010101 01010101 01010101
+# BROKEN-OUTPUT-FILE-NEXT: 8020 01010101 01010101 01010101 01010101
+# BROKEN-OUTPUT-FILE-NEXT: 8030 01010101 01010101 01010101 01010101
 # Starting here the contents of .sec2 overwrites .sec1:
-# BROKEN-OUTPUT-FILE-NEXT: 8040 02020202 02020202 02020202 02020202  ................
+# BROKEN-OUTPUT-FILE-NEXT: 8040 02020202 02020202 02020202 02020202
 
 # RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t.so | FileCheck %s -check-prefix BAD-BOTH
 # BAD-BOTH-LABEL: Section Headers:
-# BAD-BOTH: .sec1             PROGBITS        0000000000008000 018000 000100 00  WA  0   0  1
-# BAD-BOTH: .sec2             PROGBITS        0000000000008040 018040 000100 00  WA  0   0  1
+# BAD-BOTH: .sec1             PROGBITS        0000000000008000 002000 000100 00  WA  0   0  1
+# BAD-BOTH: .sec2             PROGBITS        0000000000008040 002040 000100 00  WA  0   0  1
 # BAD-BOTH-LABEL: Program Headers:
 # BAD-BOTH-NEXT:  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
-# BAD-BOTH-NEXT:  LOAD           0x010000 0x0000000000000000 0x0000000000000000 0x0001e1 0x0001e1 R E 0x10000
-# BAD-BOTH-NEXT:  LOAD           0x018000 0x0000000000008000 0x0000000000008000 0x000150 0x000150 RW  0x10000
+# BAD-BOTH-NEXT:  LOAD           0x001000 0x0000000000000000 0x0000000000000000 0x0000fd 0x0000fd R E 0x1000
+# BAD-BOTH-NEXT:  LOAD           0x002000 0x0000000000008000 0x0000000000008000 0x0001b0 0x0001b0 RW  0x1000
 # BAD-BOTH-LABEL: Section to Segment mapping:
-# BAD-BOTH:   01     .sec1 .sec2 .data .got
-
+# BAD-BOTH:   01     .sec1 .sec2 .dynamic
 
 .section        .first_sec,"aw",@progbits
 .rept 0x100
diff --git a/test/ELF/linkerscript/page-size-align.s b/test/ELF/linkerscript/page-size-align.s
deleted file mode 100644
index 771bb13..0000000
--- a/test/ELF/linkerscript/page-size-align.s
+++ /dev/null
@@ -1,22 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-
-# RUN: echo "SECTIONS { \
-# RUN:         . = SIZEOF_HEADERS; \
-# RUN:         .text : { *(.text) } \
-# RUN:         . = ALIGN(CONSTANT(MAXPAGESIZE)); \
-# RUN:         . = . + 0x3000; \
-# RUN:         .dynamic : { *(.dynamic) } \
-# RUN:       }" > %t.script
-
-# RUN: ld.lld -T %t.script -z max-page-size=0x4000 %t.o -o %t.so -shared
-# RUN: llvm-readobj -s %t.so | FileCheck %s
-
-# CHECK:      Name: .dynamic
-# CHECK-NEXT: Type: SHT_DYNAMIC
-# CHECK-NEXT: Flags [
-# CHECK-NEXT:   SHF_ALLOC
-# CHECK-NEXT:   SHF_WRITE
-# CHECK-NEXT: ]
-# CHECK-NEXT: Address: 0x7000
-# CHECK-NEXT: Offset: 0x3000
diff --git a/test/ELF/linkerscript/page-size-align.test b/test/ELF/linkerscript/page-size-align.test
new file mode 100644
index 0000000..f694131
--- /dev/null
+++ b/test/ELF/linkerscript/page-size-align.test
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
+# RUN: ld.lld -T %s -z max-page-size=0x4000 %t.o -o %t.so -shared
+# RUN: llvm-readobj -s %t.so | FileCheck %s
+
+SECTIONS {
+  . = SIZEOF_HEADERS;
+  .text : { *(.text) }
+  . = ALIGN(CONSTANT(MAXPAGESIZE));
+  . = . + 0x3000;
+  .dynamic : { *(.dynamic) }
+}
+
+# CHECK:      Name: .dynamic
+# CHECK-NEXT: Type: SHT_DYNAMIC
+# CHECK-NEXT: Flags [
+# CHECK-NEXT:   SHF_ALLOC
+# CHECK-NEXT:   SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x7000
+# CHECK-NEXT: Offset: 0x3000
diff --git a/test/ELF/linkerscript/parse-section-in-addr.s b/test/ELF/linkerscript/parse-section-in-addr.s
deleted file mode 100644
index 7a79f64..0000000
--- a/test/ELF/linkerscript/parse-section-in-addr.s
+++ /dev/null
@@ -1,10 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-
-# RUN: echo "SECTIONS {                                   \
-# RUN:         .foo-bar : AT(ADDR(.foo-bar)) { *(.text) } \
-# RUN:       }" > %t.script
-# RUN: ld.lld -o %t.so --script %t.script %t.o -shared
-# RUN: llvm-readelf -S %t.so | FileCheck %s
-
-# CHECK: .foo-bar
diff --git a/test/ELF/linkerscript/parse-section-in-addr.test b/test/ELF/linkerscript/parse-section-in-addr.test
new file mode 100644
index 0000000..6f42a6f
--- /dev/null
+++ b/test/ELF/linkerscript/parse-section-in-addr.test
@@ -0,0 +1,10 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
+# RUN: ld.lld -o %t.so --script %s %t.o -shared
+# RUN: llvm-readelf -S %t.so | FileCheck %s
+
+SECTIONS {
+ .foo-bar : AT(ADDR(.foo-bar)) { *(.text) }
+}
+
+# CHECK: .foo-bar
diff --git a/test/ELF/linkerscript/rosegment.s b/test/ELF/linkerscript/rosegment.test
similarity index 71%
rename from test/ELF/linkerscript/rosegment.s
rename to test/ELF/linkerscript/rosegment.test
index 3201b8b..41479e6 100644
--- a/test/ELF/linkerscript/rosegment.s
+++ b/test/ELF/linkerscript/rosegment.test
@@ -1,12 +1,14 @@
 # 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 /dev/null -o %t
 
 # Test that with linker scripts we don't create a RO PT_LOAD.
 
-# RUN: echo "SECTIONS {}" > %t.script
-# RUN: ld.lld -o %t1 --script %t.script %t -shared
+# RUN: ld.lld -o %t1 --script %s %t -shared
 # RUN: llvm-readobj -l %t1 | FileCheck %s
 
+SECTIONS {
+}
+
 # CHECK-NOT:  Type: PT_LOAD
 
 # CHECK:      Type: PT_LOAD
diff --git a/test/ELF/linkerscript/sections-va-overflow.test b/test/ELF/linkerscript/sections-va-overflow.test
new file mode 100644
index 0000000..7ede6ec
--- /dev/null
+++ b/test/ELF/linkerscript/sections-va-overflow.test
@@ -0,0 +1,22 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/sections-va-overflow.s -o %t.o
+# RUN: not ld.lld -o /dev/null --script %s %t.o 2>&1 | FileCheck %s -check-prefix=ERR
+
+PHDRS {
+  ph_headers PT_PHDR PHDRS;
+  ph_text PT_LOAD FILEHDR PHDRS FLAGS (0x1 | 0x4);
+}
+
+SECTIONS { 
+ . = 0xffffffff20000000;
+ .text : { *(.text*) } : ph_text
+ .test 0x1000 : { BYTE(0) }
+ .bss : { *(.bss*) }
+}
+
+## Section .test has VA 0x1000 and placed in the same segment as section .text
+## with VA 0xffffffff20000000. That might be technically correct, but most probably
+## is a result of a broken script file and causes file offset calculation overflow.
+## It seems we do not have to support it, so we don't and we report an error in this case.
+# ERR: error: unable to place section .text at file offset [0xFFFFFFFF20000000, 0xFFFFFFFE40000000]; check your linker script for overflows
+# ERR-NOT: unable to place section .bss
diff --git a/test/ELF/linkerscript/sort-constructors.s b/test/ELF/linkerscript/sort-constructors.s
deleted file mode 100644
index a0c23af..0000000
--- a/test/ELF/linkerscript/sort-constructors.s
+++ /dev/null
@@ -1,5 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
-# RUN: echo "SECTIONS { .aaa : { SORT(CONSTRUCTORS) } }" > %t1.script
-# RUN: ld.lld -shared -o %t1 --script %t1.script %t1.o
-# RUN: llvm-readobj %t1 > /dev/null
diff --git a/test/ELF/linkerscript/sort-constructors.test b/test/ELF/linkerscript/sort-constructors.test
new file mode 100644
index 0000000..698208a
--- /dev/null
+++ b/test/ELF/linkerscript/sort-constructors.test
@@ -0,0 +1,8 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t1.o
+# RUN: ld.lld -shared -o %t1 --script %s %t1.o
+# RUN: llvm-readobj %t1 > /dev/null
+
+SECTIONS {
+ .aaa : { SORT(CONSTRUCTORS) } 
+}
diff --git a/test/ELF/linkerscript/start-end.s b/test/ELF/linkerscript/start-end.s
deleted file mode 100644
index b68606a..0000000
--- a/test/ELF/linkerscript/start-end.s
+++ /dev/null
@@ -1,16 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: echo "SECTIONS { \
-# RUN:      .init_array : { \
-# RUN:        __init_array_start = .; \
-# RUN:        *(.init_array) \
-# RUN:        __init_array_end = .; } }" > %t.script
-# RUN: ld.lld %t.o -script %t.script -o %t 2>&1
-
-.globl _start
-.text
-_start:
-  nop
-
-.section .init_array, "aw"
-  .quad 0
diff --git a/test/ELF/linkerscript/start-end.test b/test/ELF/linkerscript/start-end.test
new file mode 100644
index 0000000..ab7504d
--- /dev/null
+++ b/test/ELF/linkerscript/start-end.test
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: echo '.section .init_array, "aw"; .quad 0' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
+# RUN: ld.lld %t.o -script %s -o %t 2>&1
+
+SECTIONS {
+  .init_array : {
+    __init_array_start = .;
+    *(.init_array)
+    __init_array_end = .;
+  }
+}
diff --git a/test/ELF/linkerscript/symbol-only-flags.s b/test/ELF/linkerscript/symbol-only-flags.s
deleted file mode 100644
index 300d8d8..0000000
--- a/test/ELF/linkerscript/symbol-only-flags.s
+++ /dev/null
@@ -1,20 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
-# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; \
-# RUN:         .tbss : { *(.tbss) }         \
-# RUN:         .foo : { bar = .; } }" > %t.script
-# RUN: ld.lld -o %t --script %t.script %t.o
-# RUN: llvm-readobj -s %t | FileCheck %s
-
-## Check .foo does not get SHF_TLS flag.
-# CHECK:     Section {
-# CHECK:       Index:
-# CHECK:       Name: .foo
-# CHECK-NEXT:  Type: SHT_NOBITS
-# CHECK-NEXT:  Flags [
-# CHECK-NEXT:    SHF_ALLOC
-# CHECK-NEXT:    SHF_WRITE
-# CHECK-NEXT:  ]
-
-.section .tbss,"awT",@nobits
-.quad 0
diff --git a/test/ELF/linkerscript/symbol-only-flags.test b/test/ELF/linkerscript/symbol-only-flags.test
new file mode 100644
index 0000000..cea2539
--- /dev/null
+++ b/test/ELF/linkerscript/symbol-only-flags.test
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: echo '.section .tbss,"awT",@nobits; .quad 0' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
+# RUN: ld.lld -o %t --script %s %t.o
+# RUN: llvm-readobj -s %t | FileCheck %s
+
+SECTIONS {
+  . = SIZEOF_HEADERS;
+  .tbss : { *(.tbss) }
+  .foo : { bar = .; }
+}
+
+## Check .foo does not get SHF_TLS flag.
+# CHECK:     Section {
+# CHECK:       Index:
+# CHECK:       Name: .foo
+# CHECK-NEXT:  Type: SHT_NOBITS
+# CHECK-NEXT:  Flags [
+# CHECK-NEXT:    SHF_ALLOC
+# CHECK-NEXT:    SHF_WRITE
+# CHECK-NEXT:  ]
diff --git a/test/ELF/linkerscript/symbol-only.s b/test/ELF/linkerscript/symbol-only.s
deleted file mode 100644
index 76d54f0..0000000
--- a/test/ELF/linkerscript/symbol-only.s
+++ /dev/null
@@ -1,21 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-
-# RUN: echo "SECTIONS { \
-# RUN:  . = SIZEOF_HEADERS; \
-# RUN:  abc : { foo = .; } \
-# RUN:  . = ALIGN(0x1000); \
-# RUN:  bar : { *(bar) } \
-# RUN: }" > %t.script
-# RUN: ld.lld -o %t1 --script %t.script %t -shared
-# RUN: llvm-objdump -section-headers -t %t1 | FileCheck %s
-# CHECK:      Sections:
-# CHECK-NEXT: Idx Name          Size      Address
-# CHECK-NEXT:   0               00000000 0000000000000000
-# CHECK:          abc           00000000 [[ADDR:[0-9a-f]*]] BSS
-# CHECK-NEXT:     bar           00000000 0000000000001000 DATA
-
-# CHECK: SYMBOL TABLE:
-# CHECK:     [[ADDR]]         abc                00000000 foo
-
-.section bar, "a"
diff --git a/test/ELF/linkerscript/symbol-only.test b/test/ELF/linkerscript/symbol-only.test
new file mode 100644
index 0000000..e2123fb
--- /dev/null
+++ b/test/ELF/linkerscript/symbol-only.test
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: echo '.section bar, "a"' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t
+# RUN: ld.lld -o %t1 --script %s %t -shared
+# RUN: llvm-objdump -section-headers -t %t1 | FileCheck %s
+
+SECTIONS {
+  . = SIZEOF_HEADERS;
+  abc : { foo = .; }
+  . = ALIGN(0x1000);
+  bar : { *(bar) }
+}
+
+# CHECK:      Sections:
+# CHECK-NEXT: Idx Name          Size      Address
+# CHECK-NEXT:   0               00000000 0000000000000000
+# CHECK:          abc           00000000 [[ADDR:[0-9a-f]*]] BSS
+# CHECK-NEXT:     bar           00000000 0000000000001000 DATA
+
+# CHECK: SYMBOL TABLE:
+# CHECK:     [[ADDR]]         abc                00000000 foo
diff --git a/test/ELF/linkerscript/symbols-non-alloc.s b/test/ELF/linkerscript/symbols-non-alloc.s
deleted file mode 100644
index e51a39e..0000000
--- a/test/ELF/linkerscript/symbols-non-alloc.s
+++ /dev/null
@@ -1,19 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-
-# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; \
-# RUN:  .text : { *(.text) }                \
-# RUN:  .nonalloc : { *(.nonalloc) }        \
-# RUN:  Sym = .;                            \
-# RUN:  }" > %t.script
-# RUN: ld.lld -o %t2 --script %t.script %t
-# RUN: llvm-objdump -section-headers -t %t2 | FileCheck %s
-
-# CHECK: Sections:
-# CHECK:  .nonalloc     00000008 0000000000000000
-
-# CHECK: SYMBOL TABLE:
-# CHECK:  0000000000000008 .nonalloc 00000000 Sym
-
-.section .nonalloc,""
- .quad 0
diff --git a/test/ELF/linkerscript/symbols-non-alloc.test b/test/ELF/linkerscript/symbols-non-alloc.test
new file mode 100644
index 0000000..6d7580a
--- /dev/null
+++ b/test/ELF/linkerscript/symbols-non-alloc.test
@@ -0,0 +1,18 @@
+# REQUIRES: x86
+# RUN: echo '.section .nonalloc,""; .quad 0' \
+# RUN:   | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t
+# RUN: ld.lld -o %t2 --script %s %t
+# RUN: llvm-objdump -section-headers -t %t2 | FileCheck %s
+
+# CHECK: Sections:
+# CHECK:  .nonalloc     00000008 0000000000000000
+
+# CHECK: SYMBOL TABLE:
+# CHECK:  0000000000000008 .nonalloc 00000000 Sym
+
+SECTIONS {
+  . = SIZEOF_HEADERS;
+  .text : { *(.text) }
+  .nonalloc : { *(.nonalloc) }
+  Sym = .;
+}
diff --git a/test/ELF/linkerscript/synthetic-relsec-layout.s b/test/ELF/linkerscript/synthetic-relsec-layout.s
new file mode 100644
index 0000000..efaa946
--- /dev/null
+++ b/test/ELF/linkerscript/synthetic-relsec-layout.s
@@ -0,0 +1,16 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "SECTIONS { .foo : { *(.rela.dyn) } }" > %t.script
+# RUN: ld.lld -T %t.script %t.o -o %t.so -shared
+# RUN: llvm-readobj -r %t.so | FileCheck %s
+
+# Check we are able to do custom layout for synthetic sections.
+# (here we check we can place synthetic .rela.dyn into .foo).
+
+# CHECK: Relocations [
+# CHECK:   Section ({{.*}}) .foo {
+# CHECK:     R_X86_64_64 .foo 0x0
+# CHECK:   }
+
+.data
+.quad .foo
diff --git a/test/ELF/linkerscript/unused-synthetic2.s b/test/ELF/linkerscript/unused-synthetic2.test
similarity index 67%
rename from test/ELF/linkerscript/unused-synthetic2.s
rename to test/ELF/linkerscript/unused-synthetic2.test
index cdde97d..755d1af 100644
--- a/test/ELF/linkerscript/unused-synthetic2.s
+++ b/test/ELF/linkerscript/unused-synthetic2.test
@@ -1,9 +1,12 @@
 # REQUIRES: arm
-# RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux-gnueabi %s -o %t.o
-# RUN: echo "SECTIONS { .trap : { *(.ARM.exidx) *(.dummy) } }" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux-gnueabi /dev/null -o %t.o
 
 ## We incorrectly removed unused synthetic sections and crashed before.
 ## Check we do not crash and do not produce .trap output section.
-# RUN: ld.lld -shared -o %t.so --script %t.script %t.o
+# RUN: ld.lld -shared -o %t.so --script %s %t.o
 # RUN: llvm-objdump -section-headers %t.so | FileCheck %s
 # CHECK-NOT: .trap
+
+SECTIONS {
+  .trap : { *(.ARM.exidx) *(.dummy) }
+}
diff --git a/test/ELF/lto-plugin-ignore.s b/test/ELF/lto-plugin-ignore.s
index 1393df9..65230f1 100644
--- a/test/ELF/lto-plugin-ignore.s
+++ b/test/ELF/lto-plugin-ignore.s
@@ -5,7 +5,6 @@
 # RUN:   -plugin-opt=-pass-through=-lgcc -plugin-opt=-function-sections \
 # RUN:   -plugin-opt=-data-sections -plugin-opt=thinlto -o /dev/null
 
-# RUN: not ld.lld %t -plugin-opt=-data-sectionxxx \
-# RUN:   -plugin-opt=-function-sectionxxx 2>&1 | FileCheck %s
-# CHECK: Unknown command line argument '-data-sectionxxx'
-# CHECK: Unknown command line argument '-function-sectionxxx'
+# RUN: not ld.lld %t -plugin-opt=-abc -plugin-opt=-xyz 2>&1 | FileCheck %s
+# CHECK: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-abc'
+# CHECK: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-xyz'
diff --git a/test/ELF/lto/version-script2.ll b/test/ELF/lto/version-script2.ll
new file mode 100644
index 0000000..ab8f75a
--- /dev/null
+++ b/test/ELF/lto/version-script2.ll
@@ -0,0 +1,15 @@
+; REQUIRES: x86
+; RUN: llvm-as %s -o %t.o
+; RUN: echo "VER1 {};" > %t.script
+; RUN: ld.lld %t.o -o %t.so -shared --version-script %t.script
+; RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+; test that we have the correct version.
+; CHECK: Name: foo@@VER1 (
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm ".global foo"
+module asm "foo:"
+module asm ".symver foo,foo@@@VER1"
diff --git a/test/ELF/map-file.s b/test/ELF/map-file.s
index 989ae7d..23b9381 100644
--- a/test/ELF/map-file.s
+++ b/test/ELF/map-file.s
@@ -15,6 +15,8 @@
 
 .global _start
 _start:
+.cfi_startproc
+.cfi_endproc
  .quad sharedFoo
  .quad sharedBar
  .byte 0xe8
@@ -26,8 +28,8 @@
 .global _Z1fi
 _Z1fi:
 .cfi_startproc
-.cfi_endproc
 nop
+.cfi_endproc
 .weak bar
 bar:
 .long bar - .
@@ -51,8 +53,10 @@
 // CHECK-NEXT: 00000000002002d0 0000000000000030     8         <internal>:(.rela.dyn)
 // CHECK-NEXT: 0000000000200300 0000000000000030     8 .rela.plt
 // CHECK-NEXT: 0000000000200300 0000000000000030     8         <internal>:(.rela.plt)
-// CHECK-NEXT: 0000000000200330 0000000000000030     8 .eh_frame
-// CHECK-NEXT: 0000000000200330 0000000000000030     8         <internal>:(.eh_frame)
+// CHECK-NEXT: 0000000000200330 0000000000000060     8 .eh_frame
+// CHECK-NEXT: 0000000000200330 000000000000002c     0         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x0)
+// CHECK-NEXT: 0000000000200360 0000000000000014     0         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x2c)
+// CHECK-NEXT: 0000000000200378 0000000000000018     0         {{.*}}{{/|\\}}map-file.s.tmp2.o:(.eh_frame+0x18)
 // CHECK-NEXT: 0000000000201000 000000000000002d     4 .text
 // CHECK-NEXT: 0000000000201000 0000000000000028     4         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.text)
 // CHECK-NEXT: 0000000000201000 0000000000000000     0                 _start
diff --git a/test/ELF/merge-reloc-O0.s b/test/ELF/merge-reloc-O0.s
new file mode 100644
index 0000000..daf5c34
--- /dev/null
+++ b/test/ELF/merge-reloc-O0.s
@@ -0,0 +1,48 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -r -o %t2.o -O0
+# RUN: llvm-readobj -s -section-data %t2.o | FileCheck %s
+
+# We combine just the sections with the same name and sh_entsize.
+
+# CHECK:      Name: .foo
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT:   SHF_ALLOC
+# CHECK-NEXT:   SHF_MERGE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size: 16
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 8
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT:   0000: 41000000 00000000 42000000 00000000
+# CHECK-NEXT: )
+
+# CHECK:      Name: .foo
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT:   SHF_ALLOC
+# CHECK-NEXT:   SHF_MERGE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size: 8
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 4
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT:   0000: 41000000 42000000
+# CHECK-NEXT: )
+
+        .section .foo, "aM",@progbits,8,unique,0
+        .quad 0x41
+        .section .foo, "aM",@progbits,8,unique,1
+        .quad 0x42
+        .section .foo, "aM",@progbits,4,unique,2
+        .long 0x41
+        .long 0x42
diff --git a/test/ELF/multiple-cu.s b/test/ELF/multiple-cu.s
new file mode 100644
index 0000000..df2b94d
--- /dev/null
+++ b/test/ELF/multiple-cu.s
@@ -0,0 +1,38 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/multiple-cu.s -o %t2.o
+# RUN: ld.lld -r -o %t.o %t1.o %t2.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# CHECK:      error: undefined symbol: foo
+# CHECK-NEXT: referenced by test1.c:2
+
+# CHECK:      error: undefined symbol: bar
+# CHECK-NEXT: referenced by test2.c:2
+
+        .globl  _start
+_start:
+        .file   1 "test1.c"
+        .loc    1 2 0
+        jmp     foo
+
+        .section        .debug_abbrev,"",@progbits
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   0                       # DW_CHILDREN_no
+        .byte   16                      # DW_AT_stmt_list
+        .byte   23                      # DW_FORM_sec_offset
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+
+        .section        .debug_info,"",@progbits
+        .long   .Lend0 - .Lbegin0       # Length of Unit
+.Lbegin0:
+        .short  4                       # DWARF version number
+        .long   .debug_abbrev           # Offset Into Abbrev. Section
+        .byte   8                       # Address Size (in bytes)
+        .byte   1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+        .long   .debug_line             # DW_AT_stmt_list
+.Lend0:
+        .section        .debug_line,"",@progbits
diff --git a/test/ELF/ppc64_entry_point.s b/test/ELF/ppc64_entry_point.s
new file mode 100644
index 0000000..b3bd5ec
--- /dev/null
+++ b/test/ELF/ppc64_entry_point.s
@@ -0,0 +1,36 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -D %t2 | FileCheck %s
+
+.text
+.abiversion 2
+.globl  _start
+.p2align        4
+.type   _start,@function
+
+_start:
+.Lfunc_begin0:
+.Lfunc_gep0:
+  lis   4, .Lfunc_gep0@ha
+  addi  4, 4, .Lfunc_gep0@l
+  # now r4 should contain the address of _start
+
+  lis   5, .TOC.-.Lfunc_gep0@ha
+  addi  5, 5, .TOC.-.Lfunc_gep0@l
+  # now r5 should contain the offset s.t. r4 + r5 = TOC base
+
+  # exit 55
+  li    0, 1
+  li    3, 55
+  sc
+.Lfunc_end0:
+    .size   _start, .Lfunc_end0-.Lfunc_begin0
+
+// CHECK: 10010000:       01 10 80 3c     lis 4, 4097
+// CHECK-NEXT: 10010004:       00 00 84 38     addi 4, 4, 0
+// CHECK-NEXT: 10010008:       02 00 a0 3c     lis 5, 2
+// CHECK-NEXT: 1001000c:       00 80 a5 38     addi 5, 5, -32768
+// CHECK: Disassembly of section .got:
+// CHECK-NEXT: .got:
+// CHECK-NEXT: 10020000:       00 80 02 10
diff --git a/test/ELF/relocatable-comdat-multiple.s b/test/ELF/relocatable-comdat-multiple.s
index 4c3e7ce..935fbdc 100644
--- a/test/ELF/relocatable-comdat-multiple.s
+++ b/test/ELF/relocatable-comdat-multiple.s
@@ -8,6 +8,8 @@
 # CHECK-NEXT:   Group {
 # CHECK-NEXT:     Name: .group
 # CHECK-NEXT:     Index: 2
+# CHECK-NEXT:     Link: 8
+# CHECK-NEXT:     Info: 1
 # CHECK-NEXT:     Type: COMDAT
 # CHECK-NEXT:     Signature: aaa
 # CHECK-NEXT:     Section(s) in group [
@@ -18,6 +20,8 @@
 # CHECK-NEXT:   Group {
 # CHECK-NEXT:     Name: .group
 # CHECK-NEXT:     Index: 5
+# CHECK-NEXT:     Link: 8
+# CHECK-NEXT:     Info: 2
 # CHECK-NEXT:     Type: COMDAT
 # CHECK-NEXT:     Signature: bbb
 # CHECK-NEXT:     Section(s) in group [
diff --git a/test/ELF/relocatable-comdat.s b/test/ELF/relocatable-comdat.s
index 24504d2..11aa30c 100644
--- a/test/ELF/relocatable-comdat.s
+++ b/test/ELF/relocatable-comdat.s
@@ -30,6 +30,8 @@
 # CHECK-NEXT:    Group {
 # CHECK-NEXT:      Name: .group
 # CHECK-NEXT:      Index: 2
+# CHECK-NEXT:      Link: 5
+# CHECK-NEXT:      Info: 1 
 # CHECK-NEXT:      Type: COMDAT
 # CHECK-NEXT:      Signature: abc
 # CHECK-NEXT:      Section(s) in group [
diff --git a/test/ELF/relocatable-comdat2.s b/test/ELF/relocatable-comdat2.s
index 2643e64..27844fe 100644
--- a/test/ELF/relocatable-comdat2.s
+++ b/test/ELF/relocatable-comdat2.s
@@ -13,6 +13,8 @@
 # CHECK-NEXT:   Group {
 # CHECK-NEXT:     Name: .group
 # CHECK-NEXT:     Index: 2
+# CHECK-NEXT:     Link: 7
+# CHECK-NEXT:     Info: 1
 # CHECK-NEXT:     Type: COMDAT
 # CHECK-NEXT:     Signature: bar
 # CHECK-NEXT:     Section(s) in group [
@@ -22,6 +24,8 @@
 # CHECK-NEXT:   Group {
 # CHECK-NEXT:     Name: .group
 # CHECK-NEXT:     Index: 4
+# CHECK-NEXT:     Link: 7
+# CHECK-NEXT:     Info: 2
 # CHECK-NEXT:     Type: COMDAT
 # CHECK-NEXT:     Signature: zed
 # CHECK-NEXT:     Section(s) in group [
diff --git a/test/ELF/relocation-size-err.s b/test/ELF/relocation-size-err.s
index 7bef45b..763ad87 100644
--- a/test/ELF/relocation-size-err.s
+++ b/test/ELF/relocation-size-err.s
@@ -2,7 +2,7 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 // RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
 
-// CHECK:  error: can't create dynamic relocation R_X86_64_SIZE64 against symbol: foo in readonly segment; recompile object files with -fPIC
+// CHECK:  error: can't create dynamic relocation R_X86_64_SIZE64 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
 
         .global foo
 foo:
diff --git a/test/ELF/section-metadata-err.s b/test/ELF/section-metadata-err.s
index 1bcbedf..ba102be 100644
--- a/test/ELF/section-metadata-err.s
+++ b/test/ELF/section-metadata-err.s
@@ -3,7 +3,7 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
 
-# CHECK: error: a section with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err.s.tmp.o:(.foo)
+# CHECK: error: a section .bar with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err.s.tmp.o:(.foo)
 
 .global _start
 _start:
@@ -12,4 +12,4 @@
 .section .foo,"aM",@progbits,8
 .quad 0
 
-.section bar,"ao",@progbits,.foo
+.section .bar,"ao",@progbits,.foo
diff --git a/test/ELF/section-metadata-err2.s b/test/ELF/section-metadata-err2.s
new file mode 100644
index 0000000..b2b611f
--- /dev/null
+++ b/test/ELF/section-metadata-err2.s
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+## Check we do not crash and report proper errors.
+# CHECK: error: a section .bar with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err2.s.tmp.o:(.foo)
+# CHECK: error: a section .bar with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err2.s.tmp.o:(.foo)
+
+.section .foo,"aM",@progbits,8
+.quad 0
+
+.section .bar,"ao",@progbits,.foo,unique,1
+.quad 0
+
+.section .bar,"ao",@progbits,.foo,unique,2
+.quad 1
diff --git a/test/ELF/section-metadata-err3.s b/test/ELF/section-metadata-err3.s
new file mode 100644
index 0000000..36666bf
--- /dev/null
+++ b/test/ELF/section-metadata-err3.s
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# CHECK:      error: incompatible section flags for .bar
+# CHECK-NEXT: >>> {{.*}}section-metadata-err3.s.tmp.o:(.bar): 0x2
+# CHECK-NEXT: >>> output section .bar: 0x82
+
+.section .foo,"a",@progbits
+.quad 0
+
+.section .bar,"ao",@progbits,.foo,unique,1
+.quad 0
+
+.section .bar,"a",@progbits,unique,2
+.quad 1
diff --git a/test/ELF/silent-ignore.test b/test/ELF/silent-ignore.test
index 6655754..adfc244 100644
--- a/test/ELF/silent-ignore.test
+++ b/test/ELF/silent-ignore.test
@@ -1,6 +1,5 @@
 RUN: ld.lld --version \
 RUN:   -allow-shlib-undefined \
-RUN:   -cref \
 RUN:   -g \
 RUN:   -no-add-needed \
 RUN:   -no-allow-shlib-undefined \
diff --git a/test/ELF/startstop-shared.s b/test/ELF/startstop-shared.s
index 80ccf3d..4d3192a 100644
--- a/test/ELF/startstop-shared.s
+++ b/test/ELF/startstop-shared.s
@@ -11,18 +11,30 @@
         .quad __start_bar
         .section bar,"a"
 
-// Test that we are able to hide the symbol.
-// CHECK:      R_X86_64_RELATIVE - 0x[[ADDR:.*]]
+// CHECK:      Relocations [
+// CHECK-NEXT:   Section {{.*}} .rela.dyn {
+// CHECK-NEXT:     R_X86_64_RELATIVE
+// CHECK-NEXT:     R_X86_64_RELATIVE
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
 
-// By default the symbol is visible and we need a dynamic reloc.
-// CHECK:  R_X86_64_64 __start_foo 0x0
+// Test that we are able to hide the symbol.
+// By default the symbol is protected.
 
 // CHECK:      Name: __start_bar
-// CHECK-NEXT: Value: 0x[[ADDR]]
+// CHECK-NEXT: Value:
 // CHECK-NEXT: Size:
 // CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [
+// CHECK-NEXT:   STV_HIDDEN
+// CHECK-NEXT: ]
 
 // CHECK:      Name: __start_foo
 // CHECK-NEXT: Value:
 // CHECK-NEXT: Size:
 // CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [
+// CHECK-NEXT:   STV_PROTECTED
+// CHECK-NEXT: ]
diff --git a/test/ELF/startstop.s b/test/ELF/startstop.s
index 1e75042..470298e 100644
--- a/test/ELF/startstop.s
+++ b/test/ELF/startstop.s
@@ -19,13 +19,12 @@
 // DISASM:    1013:       90      nop
 // DISASM:    1014:       90      nop
 
-
 // SYMBOL:      Relocations [
 // SYMBOL-NEXT:   Section ({{.*}}) .rela.dyn {
-// SYMBOL-NEXT:     0x2010 R_X86_64_64 __stop_zed1 0x0
-// SYMBOL-NEXT:     0x2018 R_X86_64_64 __stop_zed1 0x1
-// SYMBOL-NEXT:     0x2000 R_X86_64_64 __stop_zed2 0x0
-// SYMBOL-NEXT:     0x2008 R_X86_64_64 __stop_zed2 0x1
+// SYMBOL-NEXT:     R_X86_64_RELATIVE
+// SYMBOL-NEXT:     R_X86_64_RELATIVE
+// SYMBOL-NEXT:     R_X86_64_RELATIVE
+// SYMBOL-NEXT:     R_X86_64_RELATIVE
 // SYMBOL-NEXT:   }
 // SYMBOL-NEXT: ]
 
@@ -45,20 +44,20 @@
 // SYMBOL: Symbol {
 // SYMBOL:   Name: __stop_foo
 // SYMBOL:   Value: 0x1012
-// STMBOL:   STV_HIDDEN
+// SYMBOL:   STV_HIDDEN
 // SYMBOL:   Section: foo
 // SYMBOL: }
 
 // SYMBOL: Symbol {
 // SYMBOL:   Name: __stop_zed1
 // SYMBOL:   Value: 0x2010
-// STMBOL:   Other: 0
+// SYMBOL:   STV_PROTECTED
 // SYMBOL:   Section: zed1
 // SYMBOL: }
 // SYMBOL: Symbol {
 // SYMBOL:   Name: __stop_zed2
 // SYMBOL:   Value: 0x2020
-// STMBOL:   Other: 0
+// SYMBOL:   STV_PROTECTED
 // SYMBOL:   Section: zed2
 // SYMBOL: }
 
diff --git a/test/ELF/symbol-ordering-file-warnings.s b/test/ELF/symbol-ordering-file-warnings.s
index 2918c96..aabac53 100644
--- a/test/ELF/symbol-ordering-file-warnings.s
+++ b/test/ELF/symbol-ordering-file-warnings.s
@@ -6,79 +6,81 @@
 
 # Check that a warning is emitted for entries in the file that are not present in any used input.
 # RUN: echo "missing" > %t-order-missing.txt
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,MISSING
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,MISSING
 
 # Check that the warning can be disabled.
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all --no-warn-symbol-ordering 2>&1 | \
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt \
+# RUN:   --unresolved-symbols=ignore-all --no-warn-symbol-ordering 2>&1 | \
 # RUN:   FileCheck %s --check-prefixes=WARN --allow-empty
 
 # Check that the warning can be re-enabled
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all --no-warn-symbol-ordering --warn-symbol-ordering 2>&1 | \
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt \
+# RUN:   --unresolved-symbols=ignore-all --no-warn-symbol-ordering --warn-symbol-ordering 2>&1 | \
 # RUN:   FileCheck %s --check-prefixes=WARN,MISSING
 
 # Check that a warning is emitted for undefined symbols.
 # RUN: echo "undefined" > %t-order-undef.txt
-# RUN: ld.lld %t1.o %t3.o -o %t --symbol-ordering-file %t-order-undef.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,UNDEFINED
+# RUN: ld.lld %t1.o %t3.o -o %t --symbol-ordering-file %t-order-undef.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,UNDEFINED
 
 # Check that a warning is emitted for imported shared symbols.
 # RUN: echo "shared" > %t-order-shared.txt
-# RUN: ld.lld %t1.o %t.so -o %t --symbol-ordering-file %t-order-shared.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,SHARED
+# RUN: ld.lld %t1.o %t.so -o %t --symbol-ordering-file %t-order-shared.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,SHARED
 
 # Check that a warning is emitted for absolute symbols.
 # RUN: echo "absolute" > %t-order-absolute.txt
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-absolute.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,ABSOLUTE
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-absolute.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,ABSOLUTE
 
 # Check that a warning is emitted for symbols discarded due to --gc-sections.
 # RUN: echo "gc" > %t-order-gc.txt
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-gc.txt --gc-sections --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,GC
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-gc.txt --gc-sections \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,GC
 
 # Check that a warning is emitted for the symbol removed due to --icf.
 # RUN: echo "icf1" > %t-order-icf.txt
 # RUN: echo "icf2" >> %t-order-icf.txt
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-icf.txt --icf=all --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,ICF
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-icf.txt --icf=all \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,ICF
 
 # Check that a warning is emitted for symbols discarded due to a linker script /DISCARD/ section.
 # RUN: echo "discard" > %t-order-discard.txt
 # RUN: echo "SECTIONS { /DISCARD/ : { *(.text.discard) } }" > %t.script
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-discard.txt -T %t.script --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,DISCARD
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-discard.txt -T %t.script \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,DISCARD
 
 # Check that LLD does not warn for discarded COMDAT symbols, if they are present in the kept instance.
 # RUN: echo "comdat" > %t-order-comdat.txt
-# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-comdat.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN --allow-empty
+# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-comdat.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN --allow-empty
 
 # Check that if a COMDAT was unused and discarded via --gc-sections, warn for each instance.
-# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-comdat.txt --gc-sections --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,COMDAT
+# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-comdat.txt --gc-sections \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,COMDAT
 
 # Check that if a weak symbol is not kept, because of an equivalent global symbol, no warning is emitted.
 # RUN: echo "glob_or_wk" > %t-order-weak.txt
-# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-weak.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN --allow-empty
+# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-weak.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN --allow-empty
 
 # Check that symbols only in unused archive members result in a warning.
 # RUN: rm -f %t.a
 # RUN: llvm-ar rc %t.a %t3.o
-# RUN: ld.lld %t1.o %t.a -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,MISSING --allow-empty
+# RUN: ld.lld %t1.o %t.a -o %t --symbol-ordering-file %t-order-missing.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,MISSING --allow-empty
 
 # Check that a warning for each same-named symbol with an issue.
 # RUN: echo "multi" > %t-order-same-name.txt
-# RUN: ld.lld %t1.o %t2.o %t3.o -o %t --symbol-ordering-file %t-order-same-name.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,MULTI
+# RUN: ld.lld %t1.o %t2.o %t3.o -o %t --symbol-ordering-file %t-order-same-name.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,MULTI
 
 # Check that a warning is emitted if the same symbol is mentioned multiple times in the ordering file.
 # RUN: echo "_start" > %t-order-multiple-same.txt
 # RUN: echo "_start" >> %t-order-multiple-same.txt
-# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-multiple-same.txt --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,SAMESYM
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-multiple-same.txt \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,SAMESYM
 
 # Check that all warnings can be emitted from the same input.
 # RUN: echo "missing_sym" > %t-order-multi.txt
@@ -89,8 +91,8 @@
 # RUN: echo "gc" >> %t-order-multi.txt
 # RUN: echo "discard" >> %t-order-multi.txt
 # RUN: echo "_start" >> %t-order-multi.txt
-# RUN: ld.lld %t1.o %t3.o %t.so -o %t --symbol-ordering-file %t-order-multi.txt --gc-sections -T %t.script --unresolved-symbols=ignore-all 2>&1 | \
-# RUN:   FileCheck %s --check-prefixes=WARN,SAMESYM,ABSOLUTE,SHARED,UNDEFINED,GC,DISCARD,MISSING2
+# RUN: ld.lld %t1.o %t3.o %t.so -o %t --symbol-ordering-file %t-order-multi.txt --gc-sections -T %t.script \
+# RUN:   --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,SAMESYM,ABSOLUTE,SHARED,UNDEFINED,GC,DISCARD,MISSING2
 
 # WARN-NOT:    warning:
 # SAMESYM:     warning: {{.*}}.txt: duplicate ordered symbol: _start
diff --git a/test/ELF/tls-got.s b/test/ELF/tls-got.s
index b1686cd..a0261ee 100644
--- a/test/ELF/tls-got.s
+++ b/test/ELF/tls-got.s
@@ -25,13 +25,13 @@
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section (4) .rela.dyn {
 // CHECK-NEXT:     0x2020B8 R_X86_64_TPOFF64 tls0 0x0
-// CHECK-NEXT:     [[ADDR]] R_X86_64_TPOFF64 tls1 0x0
+// CHECK-NEXT:     0x2020B0 R_X86_64_TPOFF64 tls1 0x0
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
-//0x201000 + 4249 + 7 = 0x2020B0
-//0x20100A + 4247 + 7 = 0x2020B8
-//0x201014 + 4237 + 7 = 0x2020B8
+//0x201000 + 4265 + 7 = 0x2020B0
+//0x20100A + 4263 + 7 = 0x2020B8
+//0x201014 + 4253 + 7 = 0x2020B8
 //DISASM:      Disassembly of section .text:
 //DISASM-NEXT: main:
 //DISASM-NEXT: 201000: 48 8b 05 a9 10 00 00 movq 4265(%rip), %rax
diff --git a/test/ELF/undef-broken-debug.test b/test/ELF/undef-broken-debug.test
index 1238ebe..4a61bce 100644
--- a/test/ELF/undef-broken-debug.test
+++ b/test/ELF/undef-broken-debug.test
@@ -40,6 +40,27 @@
       - Offset:          0x0000000000000029
         Symbol:          bar
         Type:            R_X86_64_64
+  - Name:            .debug_info
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         0C000000040000000000080100000000
+  - Name:            .rela.debug_info
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .debug_info
+    Relocations:
+      - Offset:          0x0000000000000006
+        Symbol:          .debug_abbrev
+        Type:            R_X86_64_32
+      - Offset:          0x000000000000000C
+        Symbol:          .debug_line
+        Type:            R_X86_64_32
+  - Name:            .debug_abbrev
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         '0111001017000000'
+
 Symbols:
   Global:
     - Name:            _start
diff --git a/test/ELF/undef.s b/test/ELF/undef.s
index 49f8410..aabcbbc 100644
--- a/test/ELF/undef.s
+++ b/test/ELF/undef.s
@@ -2,9 +2,10 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/undef.s -o %t2.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/undef-debug.s -o %t3.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/undef-bad-debug.s -o %t4.o
 # RUN: llvm-ar rc %t2.a %t2.o
-# RUN: not ld.lld %t.o %t2.a %t3.o -o %t.exe 2>&1 | FileCheck %s
-# RUN: not ld.lld -pie %t.o %t2.a %t3.o -o %t.exe 2>&1 | FileCheck %s
+# RUN: not ld.lld %t.o %t2.a %t3.o %t4.o -o %t.exe 2>&1 | FileCheck %s
+# RUN: not ld.lld -pie %t.o %t2.a %t3.o %t4.o -o %t.exe 2>&1 | FileCheck %s
 
 # CHECK: error: undefined symbol: foo
 # CHECK: >>> referenced by undef.s
@@ -33,6 +34,9 @@
 # CHECK: >>> referenced by undef-debug.s:11 (dir{{/|\\}}undef-debug.s:11)
 # CHECK: >>>               {{.*}}.o:(.text.2+0x0)
 
+# CHECK: error: undefined symbol: zed6
+# CHECK: >>> referenced by {{.*}}tmp4.o:(.text+0x0)
+
 # RUN: not ld.lld %t.o %t2.a -o %t.exe -no-demangle 2>&1 | \
 # RUN:   FileCheck -check-prefix=NO-DEMANGLE %s
 # NO-DEMANGLE: error: undefined symbol: _Z3fooi
diff --git a/test/ELF/x86-64-reloc-debug-overflow.s b/test/ELF/x86-64-reloc-debug-overflow.s
new file mode 100644
index 0000000..364c3bf
--- /dev/null
+++ b/test/ELF/x86-64-reloc-debug-overflow.s
@@ -0,0 +1,9 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/x86-64-reloc-error.s -o %tabs
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+# RUN: not ld.lld -shared %tabs %t -o %t2 2>&1 | FileCheck %s
+
+# CHECK: (.debug_info+0x0): relocation R_X86_64_32 out of range: 281474976710656 is not in [0, 4294967295]; consider recompiling with -fdebug-types-section to reduce size of debug sections
+
+.section .debug_info,"",@progbits
+ .long .debug_info + 0x1000000000000
diff --git a/test/ELF/x86-64-retpoline-linkerscript.s b/test/ELF/x86-64-retpoline-linkerscript.s
new file mode 100644
index 0000000..d173cf5
--- /dev/null
+++ b/test/ELF/x86-64-retpoline-linkerscript.s
@@ -0,0 +1,67 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+
+// RUN: echo "SECTIONS { \
+// RUN:   .text : { *(.text) } \
+// RUN:   .plt : { *(.plt) } \
+// RUN:   .got.plt : { *(.got.plt) } \
+// RUN:   .dynstr : { *(.dynstr) } \
+// RUN: }" > %t.script
+// RUN: ld.lld -shared %t1.o %t2.so -o %t.exe -z retpolineplt --script %t.script
+// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
+
+// CHECK:      Disassembly of section .plt:
+// CHECK-NEXT: .plt:
+// CHECK-NEXT: 10:       ff 35 4a 01 00 00       pushq   330(%rip)
+// CHECK-NEXT: 16:       4c 8b 1d 4b 01 00 00    movq    331(%rip), %r11
+// CHECK-NEXT: 1d:       e8 0e 00 00 00  callq   14 <.plt+0x20>
+// CHECK-NEXT: 22:       f3 90   pause
+// CHECK-NEXT: 24:       0f ae e8        lfence
+// CHECK-NEXT: 27:       eb f9   jmp     -7 <.plt+0x12>
+// CHECK-NEXT: 29:       cc      int3
+// CHECK-NEXT: 2a:       cc      int3
+// CHECK-NEXT: 2b:       cc      int3
+// CHECK-NEXT: 2c:       cc      int3
+// CHECK-NEXT: 2d:       cc      int3
+// CHECK-NEXT: 2e:       cc      int3
+// CHECK-NEXT: 2f:       cc      int3
+// CHECK-NEXT: 30:       4c 89 1c 24     movq    %r11, (%rsp)
+// CHECK-NEXT: 34:       c3      retq
+// CHECK-NEXT: 35:       cc      int3
+// CHECK-NEXT: 36:       cc      int3
+// CHECK-NEXT: 37:       cc      int3
+// CHECK-NEXT: 38:       cc      int3
+// CHECK-NEXT: 39:       cc      int3
+// CHECK-NEXT: 3a:       cc      int3
+// CHECK-NEXT: 3b:       cc      int3
+// CHECK-NEXT: 3c:       cc      int3
+// CHECK-NEXT: 3d:       cc      int3
+// CHECK-NEXT: 3e:       cc      int3
+// CHECK-NEXT: 3f:       cc      int3
+// CHECK-NEXT: 40:       4c 8b 1d 29 01 00 00    movq    297(%rip), %r11
+// CHECK-NEXT: 47:       e8 e4 ff ff ff  callq   -28 <.plt+0x20>
+// CHECK-NEXT: 4c:       e9 d1 ff ff ff  jmp     -47 <.plt+0x12>
+// CHECK-NEXT: 51:       68 00 00 00 00  pushq   $0
+// CHECK-NEXT: 56:       e9 b5 ff ff ff  jmp     -75 <.plt>
+// CHECK-NEXT: 5b:       cc      int3
+// CHECK-NEXT: 5c:       cc      int3
+// CHECK-NEXT: 5d:       cc      int3
+// CHECK-NEXT: 5e:       cc      int3
+// CHECK-NEXT: 5f:       cc      int3
+// CHECK-NEXT: 60:       4c 8b 1d 11 01 00 00    movq    273(%rip), %r11
+// CHECK-NEXT: 67:       e8 c4 ff ff ff  callq   -60 <.plt+0x20>
+// CHECK-NEXT: 6c:       e9 b1 ff ff ff  jmp     -79 <.plt+0x12>
+// CHECK-NEXT: 71:       68 01 00 00 00  pushq   $1
+// CHECK-NEXT: 76:       e9 95 ff ff ff  jmp     -107 <.plt>
+// CHECK-NEXT: 7b:       cc      int3
+// CHECK-NEXT: 7c:       cc      int3
+// CHECK-NEXT: 7d:       cc      int3
+// CHECK-NEXT: 7e:       cc      int3
+// CHECK-NEXT: 7f:       cc      int3
+
+.global _start
+_start:
+  jmp bar@PLT
+  jmp zed@PLT
diff --git a/test/ELF/x86-64-retpoline-znow-linkerscript.s b/test/ELF/x86-64-retpoline-znow-linkerscript.s
new file mode 100644
index 0000000..27737b8
--- /dev/null
+++ b/test/ELF/x86-64-retpoline-znow-linkerscript.s
@@ -0,0 +1,54 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+
+// RUN: echo "SECTIONS { \
+// RUN:   .text : { *(.text) } \
+// RUN:   .plt : { *(.plt) } \
+// RUN:   .got.plt : { *(.got.plt) } \
+// RUN:   .dynstr : { *(.dynstr) } \
+// RUN: }" > %t.script
+// RUN: ld.lld -shared %t1.o %t2.so -o %t.exe -z retpolineplt -z now --script %t.script
+// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
+
+// CHECK:      Disassembly of section .plt:
+// CHECK-NEXT: .plt:
+// CHECK-NEXT: 10:	e8 0b 00 00 00 	callq	11 <.plt+0x10>
+// CHECK-NEXT: 15:	f3 90 	pause
+// CHECK-NEXT: 17:	0f ae e8 	lfence
+// CHECK-NEXT: 1a:	eb f9 	jmp	-7 <.plt+0x5>
+// CHECK-NEXT: 1c:	cc 	int3
+// CHECK-NEXT: 1d:	cc 	int3
+// CHECK-NEXT: 1e:	cc 	int3
+// CHECK-NEXT: 1f:	cc 	int3
+// CHECK-NEXT: 20:	4c 89 1c 24 	movq	%r11, (%rsp)
+// CHECK-NEXT: 24:	c3 	retq
+// CHECK-NEXT: 25:	cc 	int3
+// CHECK-NEXT: 26:	cc 	int3
+// CHECK-NEXT: 27:	cc 	int3
+// CHECK-NEXT: 28:	cc 	int3
+// CHECK-NEXT: 29:	cc 	int3
+// CHECK-NEXT: 2a:	cc 	int3
+// CHECK-NEXT: 2b:	cc 	int3
+// CHECK-NEXT: 2c:	cc 	int3
+// CHECK-NEXT: 2d:	cc 	int3
+// CHECK-NEXT: 2e:	cc 	int3
+// CHECK-NEXT: 2f:	cc 	int3
+// CHECK-NEXT: 30:	4c 8b 1d 09 01 00 00 	movq	265(%rip), %r11
+// CHECK-NEXT: 37:	e9 d4 ff ff ff 	jmp	-44 <.plt>
+// CHECK-NEXT: 3c:	cc 	int3
+// CHECK-NEXT: 3d:	cc 	int3
+// CHECK-NEXT: 3e:	cc 	int3
+// CHECK-NEXT: 3f:	cc 	int3
+// CHECK-NEXT: 40: 4c 8b 1d 01 01 00 00 	movq	257(%rip), %r11
+// CHECK-NEXT: 47:	e9 c4 ff ff ff 	jmp	-60 <.plt>
+// CHECK-NEXT: 4c:	cc 	int3
+// CHECK-NEXT: 4d:	cc 	int3
+// CHECK-NEXT: 4e:	cc 	int3
+// CHECK-NEXT: 4f:	cc 	int3
+
+.global _start
+_start:
+  jmp bar@PLT
+  jmp zed@PLT
diff --git a/test/MinGW/driver.test b/test/MinGW/driver.test
index b0b5f56..1a95d23 100644
--- a/test/MinGW/driver.test
+++ b/test/MinGW/driver.test
@@ -126,3 +126,7 @@
 ICF: -opt:icf
 
 RUN: ld.lld -### -m i386pep --start-group foo.o --end-group
+
+RUN: ld.lld -### foo.o -m i386pe -shared --kill-at | FileCheck -check-prefix=KILL-AT %s
+RUN: ld.lld -### foo.o -m i386pe -shared -kill-at | FileCheck -check-prefix=KILL-AT %s
+KILL-AT: -kill-at
diff --git a/test/lit.cfg.py b/test/lit.cfg.py
index 05ebc23..8fd1a60 100644
--- a/test/lit.cfg.py
+++ b/test/lit.cfg.py
@@ -71,7 +71,7 @@
                           'X86': 'x86'})
      ])
 
-# Set a fake constant version so that we get consitent output.
+# Set a fake constant version so that we get consistent output.
 config.environment['LLD_VERSION'] = 'LLD 1.0'
 config.environment['LLD_IN_TEST'] = '1'
 
@@ -85,6 +85,9 @@
 if (config.llvm_libxml2_enabled == '1'):
     config.available_features.add('libxml2')
 
+if config.have_dia_sdk:
+    config.available_features.add("diasdk")
+
 tar_executable = lit.util.which('tar', config.environment['PATH'])
 if tar_executable:
     tar_version = subprocess.Popen(
diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in
index 50593f7..764ab83 100644
--- a/test/lit.site.cfg.py.in
+++ b/test/lit.site.cfg.py.in
@@ -1,5 +1,8 @@
 @LIT_SITE_CFG_IN_HEADER@
 
+import lit.util
+
+config.have_dia_sdk = lit.util.pythonize_bool("@LLVM_ENABLE_DIA_SDK@")
 config.llvm_src_root = "@LLVM_SOURCE_DIR@"
 config.llvm_obj_root = "@LLVM_BINARY_DIR@"
 config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
diff --git a/test/wasm/alias.ll b/test/wasm/alias.ll
index e5b5776..c12ef2d 100644
--- a/test/wasm/alias.ll
+++ b/test/wasm/alias.ll
@@ -66,10 +66,10 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            start_alias
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:   - Type:            CODE
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
@@ -82,7 +82,7 @@
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            _start
 ; CHECK-NEXT: ...
diff --git a/test/wasm/call-indirect.ll b/test/wasm/call-indirect.ll
index c4fa355..9a6d64f 100644
--- a/test/wasm/call-indirect.ll
+++ b/test/wasm/call-indirect.ll
@@ -57,7 +57,7 @@
 ; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:           - I32
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 3, 1, 3, 4, 3 ]
+; CHECK-NEXT:     FunctionTypes:   [ 3, 0, 3, 1, 3, 4 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -107,50 +107,50 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           3
+; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:       - Name:            bar
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            call_bar_indirect
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            foo
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            indirect_func
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            call_ptr
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:         Index:           5
 ; CHECK-NEXT:   - Type:            ELEM
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1
-; CHECK-NEXT:         Functions:       [ 0, 2 ]
+; CHECK-NEXT:         Functions:       [ 1, 3 ]
 ; CHECK-NEXT:   - Type:            CODE
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            42010B
+; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            42010B
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:            - Type:            I32
 ; CHECK-NEXT:              Count:           1
 ; CHECK-NEXT:          Body:            4100280284888080002100410028028088808000118080808000001A2000118180808000001A0B
-; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            410028028888808000118180808000001A0B
+; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            42012000118280808000001A0B
+; CHECK-NEXT:         Body:            410028028888808000118180808000001A0B
 ; CHECK-NEXT:       - Index:           5
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:         Body:            42012000118280808000001A0B
 ; CHECK-NEXT:   - Type:            DATA
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - SectionOffset:    7
@@ -163,10 +163,15 @@
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            bar
+; CHECK-NEXT:         Name:            __wasm_call_ctors
 ; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            call_bar_indirect
+; CHECK-NEXT:         Name:            bar
 ; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Name:            foo
+; CHECK-NEXT:         Name:            call_bar_indirect
 ; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            foo
+; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Name:            call_ptr
+; CHECK-NEXT: ...
diff --git a/test/wasm/comdats.ll b/test/wasm/comdats.ll
index 65e74db..d737132 100644
--- a/test/wasm/comdats.ll
+++ b/test/wasm/comdats.ll
@@ -53,42 +53,42 @@
 ; CHECK-NEXT:        Index:           2
 ; CHECK-NEXT:      - Name:            _start
 ; CHECK-NEXT:        Kind:            FUNCTION
-; CHECK-NEXT:        Index:           0
+; CHECK-NEXT:        Index:           1
 ; CHECK-NEXT:      - Name:            inlineFn
 ; CHECK-NEXT:        Kind:            FUNCTION
-; CHECK-NEXT:        Index:           1
+; CHECK-NEXT:        Index:           2
 ; CHECK-NEXT:      - Name:            constantData
 ; CHECK-NEXT:        Kind:            GLOBAL
 ; CHECK-NEXT:        Index:           3
 ; CHECK-NEXT:      - Name:            callInline1
 ; CHECK-NEXT:        Kind:            FUNCTION
-; CHECK-NEXT:        Index:           2
+; CHECK-NEXT:        Index:           3
 ; CHECK-NEXT:      - Name:            callInline2
 ; CHECK-NEXT:        Kind:            FUNCTION
-; CHECK-NEXT:        Index:           3
+; CHECK-NEXT:        Index:           4
 ; CHECK-NEXT:  - Type:            ELEM
 ; CHECK-NEXT:    Segments:
 ; CHECK-NEXT:      - Offset:
 ; CHECK-NEXT:          Opcode:          I32_CONST
 ; CHECK-NEXT:          Value:           1
-; CHECK-NEXT:        Functions:       [ 1 ]
+; CHECK-NEXT:        Functions:       [ 2 ]
 ; CHECK-NEXT:  - Type:            CODE
 ; CHECK-NEXT:    Functions:
 ; CHECK-NEXT:      - Index:           0
 ; CHECK-NEXT:        Locals:
-; CHECK-NEXT:        Body:            1081808080001A0B
+; CHECK-NEXT:        Body:            0B
 ; CHECK-NEXT:      - Index:           1
 ; CHECK-NEXT:        Locals:
-; CHECK-NEXT:        Body:            4180888080000B
+; CHECK-NEXT:        Body:            1082808080001A0B
 ; CHECK-NEXT:      - Index:           2
 ; CHECK-NEXT:        Locals:
-; CHECK-NEXT:        Body:            4181808080000B
+; CHECK-NEXT:        Body:            4180888080000B
 ; CHECK-NEXT:      - Index:           3
 ; CHECK-NEXT:        Locals:
 ; CHECK-NEXT:        Body:            4181808080000B
 ; CHECK-NEXT:      - Index:           4
 ; CHECK-NEXT:        Locals:
-; CHECK-NEXT:        Body:            0B
+; CHECK-NEXT:        Body:            4181808080000B
 ; CHECK-NEXT:  - Type:            DATA
 ; CHECK-NEXT:    Segments:
 ; CHECK-NEXT:      - SectionOffset:   7
diff --git a/test/wasm/cxx-mangling.ll b/test/wasm/cxx-mangling.ll
new file mode 100644
index 0000000..8b73ca9
--- /dev/null
+++ b/test/wasm/cxx-mangling.ll
@@ -0,0 +1,66 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: wasm-ld --demangle --check-signatures -o %t_demangle.wasm %t.o
+; RUN: obj2yaml %t_demangle.wasm | FileCheck %s
+; RUN: wasm-ld --no-demangle --check-signatures -o %t_nodemangle.wasm %t.o
+; RUN: obj2yaml %t_nodemangle.wasm | FileCheck %s
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+; Check that the EXPORT name is still mangled, but that the "name" custom
+; section contains the unmangled name.
+
+define void @_Z3fooi(i32 %arg) {
+  ret void
+}
+
+declare extern_weak void @_Z3bari(i32 %arg)
+
+define void @_start() {
+  call void @_Z3fooi(i32 1)
+  call void @_Z3bari(i32 1)
+  ret void
+}
+
+; CHECK:        - Type:            EXPORT
+; CHECK-NEXT:     Exports:
+; CHECK-NEXT:       - Name:            memory
+; CHECK-NEXT:         Kind:            MEMORY
+; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:       - Name:            __heap_base
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:       - Name:            __data_end
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:       - Name:            _start
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           3
+; CHECK-NEXT:       - Name:            _Z3fooi
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:   - Type:            CODE
+; CHECK-NEXT:     Functions:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            000B
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            410110828080800041011081808080000B
+; CHECK-NEXT:   - Type:            CUSTOM
+; CHECK-NEXT:     Name:            name
+; CHECK-NEXT:     FunctionNames:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            'undefined function bar(int)'
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            'foo(int)'
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT: ...
diff --git a/test/wasm/data-layout.ll b/test/wasm/data-layout.ll
index e1e64b3..ece5f20 100644
--- a/test/wasm/data-layout.ll
+++ b/test/wasm/data-layout.ll
@@ -9,10 +9,17 @@
 @hello_str = external global i8*
 @external_ref = global i8** @hello_str, align 8
 
+%struct.s = type { i32, i32 }
+@local_struct = hidden global %struct.s zeroinitializer, align 4
+@local_struct_internal_ptr = hidden local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @local_struct, i32 0, i32 1), align 4
+
 ; RUN: wasm-ld -no-gc-sections --check-signatures --allow-undefined -o %t.wasm %t.o %t.hello.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
-; CHECK:        - Type:            GLOBAL
+; CHECK:        - Type:            MEMORY
+; CHECK-NEXT:     Memories:
+; CHECK-NEXT:       - Initial:         0x00000002
+; CHECK-NEXT:   - Type:            GLOBAL
 ; CHECK-NEXT:     Globals:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Type:            I32
@@ -34,13 +41,32 @@
 ; CHECK-NEXT:         Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1024
-; CHECK-NEXT:         Content:         0100000000000000000000000000000003000000000000001C040000
-; CHECK-NEXT:       - SectionOffset:   41
+; CHECK-NEXT:         Content:         '0100000000000000000000000000000003000000000000002804000024040000'
+; CHECK-NEXT:       - SectionOffset:   45
 ; CHECK-NEXT:         MemoryIndex:     0
 ; CHECK-NEXT:         Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
-; CHECK-NEXT:           Value:           1052
+; CHECK-NEXT:           Value:           1056
+; CHECK-NEXT:         Content:         '0000000000000000'
+; CHECK-NEXT:       - SectionOffset:   59
+; CHECK-NEXT:         MemoryIndex:     0
+; CHECK-NEXT:         Offset:          
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           1064
 ; CHECK-NEXT:         Content:         68656C6C6F0A00
+; CHECK-NEXT:    - Type:            CUSTOM
+
+
+; RUN: wasm-ld -no-gc-sections --check-signatures --allow-undefined \
+; RUN:     --initial-memory=131072 --max-memory=131072 -o %t_max.wasm %t.o \
+; RUN:     %t.hello.o
+; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-MAX
+
+; CHECK-MAX:        - Type:            MEMORY
+; CHECK-MAX-NEXT:     Memories:
+; CHECK-MAX-NEXT:       - Flags:           [ HAS_MAX ]
+; CHECK-MAX-NEXT:         Initial:         0x00000002
+; CHECK-MAX-NEXT:         Maximum:         0x00000002
 
 
 ; RUN: wasm-ld --check-signatures --relocatable -o %t_reloc.wasm %t.o %t.hello.o
@@ -49,8 +75,12 @@
 ; RELOC:       - Type:            DATA
 ; RELOC-NEXT:     Relocations:
 ; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_I32
-; RELOC-NEXT:         Index:           4
+; RELOC-NEXT:         Index:           6
 ; RELOC-NEXT:         Offset:          0x00000018
+; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_MEMORY_ADDR_I32
+; RELOC-NEXT:         Index:           3
+; RELOC-NEXT:         Offset:          0x0000002E
+; RELOC-NEXT:         Addend:          4
 ; RELOC-NEXT:     Segments:
 ; RELOC-NEXT:       - SectionOffset:   6
 ; RELOC-NEXT:         MemoryIndex:     0
@@ -69,12 +99,24 @@
 ; RELOC-NEXT:         Offset:
 ; RELOC-NEXT:           Opcode:          I32_CONST
 ; RELOC-NEXT:           Value:           24
-; RELOC-NEXT:         Content:         1C000000
+; RELOC-NEXT:         Content:         '28000000'
 ; RELOC-NEXT:       - SectionOffset:   33
 ; RELOC-NEXT:         MemoryIndex:     0
+; RELOC-NEXT:         Offset:          
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           28
+; RELOC-NEXT:         Content:         '0000000000000000'
+; RELOC-NEXT:       - SectionOffset:   46
+; RELOC-NEXT:         MemoryIndex:     0
+; RELOC-NEXT:         Offset:          
+; RELOC-NEXT:           Opcode:          I32_CONST
+; RELOC-NEXT:           Value:           36
+; RELOC-NEXT:         Content:         '20000000'
+; RELOC-NEXT:       - SectionOffset:   55
+; RELOC-NEXT:         MemoryIndex:     0
 ; RELOC-NEXT:         Offset:
 ; RELOC-NEXT:           Opcode:          I32_CONST
-; RELOC-NEXT:           Value:           28
+; RELOC-NEXT:           Value:           40
 ; RELOC-NEXT:         Content:         68656C6C6F0A00
 
 ; RELOC:        - Type:            CUSTOM
@@ -98,9 +140,9 @@
 ; RELOC-NEXT:         Flags:           [  ]
 ; RELOC-NEXT:         Segment:         2
 ; RELOC-NEXT:         Size:            4
-; RELOC:            - Index:           4
+; RELOC:            - Index:           6
 ; RELOC-NEXT:         Kind:            DATA
 ; RELOC-NEXT:         Name:            hello_str
 ; RELOC-NEXT:         Flags:           [  ]
-; RELOC-NEXT:         Segment:         3
+; RELOC-NEXT:         Segment:         5
 ; RELOC-NEXT:         Size:            7
diff --git a/test/wasm/demangle.ll b/test/wasm/demangle.ll
new file mode 100644
index 0000000..07f9927
--- /dev/null
+++ b/test/wasm/demangle.ll
@@ -0,0 +1,17 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: not wasm-ld --check-signatures --undefined _Z3fooi \
+; RUN:     -o %t.wasm %t.o 2>&1 | FileCheck %s
+
+; CHECK: error: undefined symbol: foo(int)
+
+; RUN: not wasm-ld --check-signatures --no-demangle --undefined _Z3fooi \
+; RUN:     -o %t.wasm %t.o 2>&1 |  FileCheck -check-prefix=CHECK-NODEMANGLE %s
+
+; CHECK-NODEMANGLE: error: undefined symbol: _Z3fooi
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+define hidden void @_start() local_unnamed_addr {
+entry:
+    ret void
+}
diff --git a/test/wasm/driver.ll b/test/wasm/driver.ll
index 10a8eca..7222cb5 100644
--- a/test/wasm/driver.ll
+++ b/test/wasm/driver.ll
@@ -16,3 +16,7 @@
 ; RUN: not wasm-ld 2>&1 | FileCheck -check-prefix=BOTH %s
 ; BOTH:     error: no input files
 ; BOTH-NOT: error: no output file specified
+
+; RUN: not wasm-ld --export-table --import-table %t.o 2>&1 \
+; RUN:   | FileCheck -check-prefix=TABLE %s
+; TABLE: error: --import-table and --export-table may not be used together
diff --git a/test/wasm/entry.ll b/test/wasm/entry.ll
index 058a782..083bf97 100644
--- a/test/wasm/entry.ll
+++ b/test/wasm/entry.ll
@@ -25,7 +25,7 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            entry
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:   - Type:
 
 ; The __wasm_call_ctors is somewhat special.  Make sure we can use it
diff --git a/test/wasm/export-table.test b/test/wasm/export-table.test
new file mode 100644
index 0000000..0923af6
--- /dev/null
+++ b/test/wasm/export-table.test
@@ -0,0 +1,19 @@
+# RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.start.o
+# RUN: wasm-ld --check-signatures --export-table -o %t.wasm %t.start.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+# Verify the --export-table flag creates a table export
+
+# CHECK:        - Type:            TABLE
+# CHECK-NEXT:     Tables:
+# CHECK-NEXT:       - ElemType:        ANYFUNC
+# CHECK-NEXT:         Limits:
+# CHECK-NEXT:           Flags:           [ HAS_MAX ]
+# CHECK-NEXT:           Initial:         0x00000001
+# CHECK-NEXT:           Maximum:         0x00000001
+# CHECK-NEXT:   - Type:
+# CHECK:        - Type:            EXPORT
+# CHECK-NEXT:     Exports:
+# CHECK:            - Name:            __indirect_function_table
+# CHECK-NEXT:         Kind:            TABLE
+# CHECK-NEXT:         Index:           0
diff --git a/test/wasm/export.ll b/test/wasm/export.ll
index 05f2b4f..f2a4fff 100644
--- a/test/wasm/export.ll
+++ b/test/wasm/export.ll
@@ -30,8 +30,8 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            hidden_function
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:   - Type:            CODE
diff --git a/test/wasm/function-imports-first.ll b/test/wasm/function-imports-first.ll
index 876d4d1..be71d7c 100644
--- a/test/wasm/function-imports-first.ll
+++ b/test/wasm/function-imports-first.ll
@@ -24,25 +24,25 @@
 ; CHECK-NEXT:        ParamTypes:
 ; CHECK-NEXT:          - F32
 ; CHECK:  - Type:            FUNCTION
-; CHECK-NEXT:    FunctionTypes: [ 0, 1, 0 ]
+; CHECK-NEXT:    FunctionTypes: [ 0, 0, 1 ]
 ; CHECK:  - Type:            CODE
 ; CHECK-NEXT:    Functions:
 ; CHECK-NEXT:      - Index:           0
 ; CHECK-NEXT:        Locals:
-; CHECK-NEXT:        Body:            43000000001081808080001A0B
+; CHECK-NEXT:        Body:            0B
 ; CHECK-NEXT:      - Index:           1
 ; CHECK-NEXT:        Locals:
-; CHECK-NEXT:        Body:            41000B
+; CHECK-NEXT:        Body:            43000000001082808080001A0B
 ; CHECK-NEXT:      - Index:           2
 ; CHECK-NEXT:        Locals:
-; CHECK-NEXT:        Body:            0B
+; CHECK-NEXT:        Body:            41000B
 ; CHECK-NEXT:   - Type:            CUSTOM
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            ret32
-; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            ret32
 ; CHECK-NEXT: ...
diff --git a/test/wasm/function-imports.ll b/test/wasm/function-imports.ll
index a435cdf..742cec2 100644
--- a/test/wasm/function-imports.ll
+++ b/test/wasm/function-imports.ll
@@ -18,14 +18,14 @@
 ; CHECK:       - Type:            TYPE
 ; CHECK-NEXT:    Signatures:
 ; CHECK-NEXT:      - Index:           0
+; CHECK-NEXT:        ReturnType:      NORESULT
+; CHECK-NEXT:        ParamTypes:
+; CHECK-NEXT:      - Index:           1
 ; CHECK-NEXT:        ReturnType:      I32
 ; CHECK-NEXT:        ParamTypes:
 ; CHECK-NEXT:          - F32
-; CHECK-NEXT:      - Index:           1
-; CHECK-NEXT:        ReturnType:      NORESULT
-; CHECK-NEXT:        ParamTypes:
 ; CHECK-NEXT:  - Type:            FUNCTION
-; CHECK-NEXT:    FunctionTypes:   [ 0, 1, 1 ]
+; CHECK-NEXT:    FunctionTypes:   [ 0, 1, 0 ]
 ; CHECK:       - Type:            CODE
 ; CHECK-NEXT:    Functions:
 ; CHECK:           - Index:       0
@@ -34,9 +34,9 @@
 ; CHECK:         Name:            name
 ; CHECK-NEXT:    FunctionNames:
 ; CHECK-NEXT:      - Index:           0
-; CHECK-NEXT:        Name:            ret32
-; CHECK-NEXT:      - Index:           1
-; CHECK-NEXT:        Name:            _start
-; CHECK-NEXT:      - Index:           2
 ; CHECK-NEXT:        Name:            __wasm_call_ctors
+; CHECK-NEXT:      - Index:           1
+; CHECK-NEXT:        Name:            ret32
+; CHECK-NEXT:      - Index:           2
+; CHECK-NEXT:        Name:            _start
 ; CHECK-NEXT: ...
diff --git a/test/wasm/gc-sections.ll b/test/wasm/gc-sections.ll
index d3b3731..dec455e 100644
--- a/test/wasm/gc-sections.ll
+++ b/test/wasm/gc-sections.ll
@@ -31,10 +31,10 @@
 ; CHECK:        - Type:            TYPE
 ; CHECK-NEXT:     Signatures:      
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ReturnType:      NORESULT
 ; CHECK-NEXT:         ParamTypes:      
 ; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         ReturnType:      NORESULT
+; CHECK-NEXT:         ReturnType:      I32
 ; CHECK-NEXT:         ParamTypes:      
 ; CHECK-NEXT:   - Type:            FUNCTION
 
@@ -48,13 +48,13 @@
 ; CHECK-NEXT:         Content:         '02000000'
 ; CHECK-NEXT:   - Type:            CUSTOM
 ; CHECK-NEXT:     Name:            name
-; CHECK-NEXT:     FunctionNames:   
+; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            used_function
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            used_function
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            _start
 ; CHECK-NEXT: ...
 
 ; RUN: wasm-ld -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm %t.o
@@ -63,13 +63,13 @@
 ; NO-GC:        - Type:            TYPE
 ; NO-GC-NEXT:     Signatures:      
 ; NO-GC-NEXT:       - Index:           0
+; NO-GC-NEXT:         ReturnType:      NORESULT
+; NO-GC-NEXT:         ParamTypes:
+; NO-GC-NEXT:       - Index:           1
 ; NO-GC-NEXT:         ReturnType:      I64
 ; NO-GC-NEXT:         ParamTypes:      
-; NO-GC-NEXT:       - Index:           1
-; NO-GC-NEXT:         ReturnType:      I32
-; NO-GC-NEXT:         ParamTypes:      
 ; NO-GC-NEXT:       - Index:           2
-; NO-GC-NEXT:         ReturnType:      NORESULT
+; NO-GC-NEXT:         ReturnType:      I32
 ; NO-GC-NEXT:         ParamTypes:      
 ; NO-GC-NEXT:   - Type:            FUNCTION
 
@@ -83,16 +83,16 @@
 ; NO-GC-NEXT:         Content:         '010000000000000002000000'
 ; NO-GC-NEXT:   - Type:            CUSTOM
 ; NO-GC-NEXT:     Name:            name
-; NO-GC-NEXT:     FunctionNames:   
+; NO-GC-NEXT:     FunctionNames:
 ; NO-GC-NEXT:       - Index:           0
-; NO-GC-NEXT:         Name:            unused_function
-; NO-GC-NEXT:       - Index:           1
-; NO-GC-NEXT:         Name:            used_function
-; NO-GC-NEXT:       - Index:           2
-; NO-GC-NEXT:         Name:            _start
-; NO-GC-NEXT:       - Index:           3
 ; NO-GC-NEXT:         Name:            __wasm_call_ctors
+; NO-GC-NEXT:       - Index:           1
+; NO-GC-NEXT:         Name:            unused_function
+; NO-GC-NEXT:       - Index:           2
+; NO-GC-NEXT:         Name:            used_function
+; NO-GC-NEXT:       - Index:           3
+; NO-GC-NEXT:         Name:            _start
 ; NO-GC-NEXT: ...
 
 ; RUN: not wasm-ld --gc-sections --relocatable -o %t1.no-gc.wasm %t.o 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR
-; CHECK-ERROR: wasm-ld: error: -r and --gc-sections may not be used together
+; CHECK-ERROR: error: -r and --gc-sections may not be used together
diff --git a/test/wasm/import-memory.test b/test/wasm/import-memory.test
index ab38c7a..955d2df 100644
--- a/test/wasm/import-memory.test
+++ b/test/wasm/import-memory.test
@@ -11,3 +11,23 @@
 # CHECK-NEXT:        Kind:            MEMORY
 # CHECK-NEXT:        Memory:
 # CHECK-NEXT:          Initial:         0x00000002
+# CHECK-NEXT:  - Type:
+
+
+
+# RUN: wasm-ld --check-signatures --import-memory --initial-memory=262144 \
+# RUN:     --max-memory=327680 -o %t.max.wasm %t.start.o
+# RUN: obj2yaml %t.max.wasm | FileCheck -check-prefix=CHECK-MAX %s
+
+# Verify the --initial-memory and --max-memory arguments work with imports
+
+# CHECK-MAX:       - Type:            IMPORT
+# CHECK-MAX-NEXT:    Imports:
+# CHECK-MAX-NEXT:      - Module:          env
+# CHECK-MAX-NEXT:        Field:           memory
+# CHECK-MAX-NEXT:        Kind:            MEMORY
+# CHECK-MAX-NEXT:        Memory:
+# CHECK-MAX-NEXT:          Flags:           [ HAS_MAX ]
+# CHECK-MAX-NEXT:          Initial:         0x00000004
+# CHECK-MAX-NEXT:          Maximum:         0x00000005
+# CHECK-MAX-NEXT:  - Type:
diff --git a/test/wasm/import-table.test b/test/wasm/import-table.test
new file mode 100644
index 0000000..98e0749
--- /dev/null
+++ b/test/wasm/import-table.test
@@ -0,0 +1,18 @@
+# RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.start.o
+# RUN: wasm-ld --check-signatures --import-table -o %t.wasm %t.start.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+# Verify the --import-table flag creates a table import
+
+# CHECK:       - Type:            IMPORT
+# CHECK-NEXT:    Imports:
+# CHECK-NEXT:      - Module:          env
+# CHECK-NEXT:        Field:           __indirect_function_table
+# CHECK-NEXT:        Kind:            TABLE
+# CHECK-NEXT:        Table:
+# CHECK-NEXT:          ElemType:        ANYFUNC
+# CHECK-NEXT:          Limits:
+# CHECK-NEXT:            Flags:           [ HAS_MAX ]
+# CHECK-NEXT:            Initial:         0x00000001
+# CHECK-NEXT:            Maximum:         0x00000001
+
diff --git a/test/wasm/init-fini.ll b/test/wasm/init-fini.ll
index 7594377..1ca2008 100644
--- a/test/wasm/init-fini.ll
+++ b/test/wasm/init-fini.ll
@@ -23,6 +23,9 @@
   ret void
 }
 
+declare hidden void @externCtor()
+declare hidden void @externDtor()
+
 define i32 @__cxa_atexit(i32 %func, i32 %arg, i32 %dso_handle) {
   ret i32 0
 }
@@ -32,70 +35,96 @@
   ret void
 }
 
-@llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [
+@llvm.global_ctors = appending global [4 x { i32, void ()*, i8* }] [
   { i32, void ()*, i8* } { i32 1001, void ()* @func1, i8* null },
   { i32, void ()*, i8* } { i32 101, void ()* @func1, i8* null },
-  { i32, void ()*, i8* } { i32 101, void ()* @func2, i8* null }
+  { i32, void ()*, i8* } { i32 101, void ()* @func2, i8* null },
+  { i32, void ()*, i8* } { i32 4000, void ()* @externCtor, i8* null }
 ]
 
-@llvm.global_dtors = appending global [3 x { i32, void ()*, i8* }] [
+@llvm.global_dtors = appending global [4 x { i32, void ()*, i8* }] [
   { i32, void ()*, i8* } { i32 1001, void ()* @func3, i8* null },
   { i32, void ()*, i8* } { i32 101, void ()* @func3, i8* null },
-  { i32, void ()*, i8* } { i32 101, void ()* @func4, i8* null }
+  { i32, void ()*, i8* } { i32 101, void ()* @func4, i8* null },
+  { i32, void ()*, i8* } { i32 4000, void ()* @externDtor, i8* null }
 ]
 
-; RUN: wasm-ld --check-signatures %t.o %t.global-ctor-dtor.o -o %t.wasm
+; RUN: wasm-ld --check-signatures --allow-undefined %t.o %t.global-ctor-dtor.o -o %t.wasm
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
+; CHECK:        - Type:            IMPORT
+; CHECK-NEXT:     Imports:
+; CHECK-NEXT:       - Module:          env
+; CHECK-NEXT:         Field:           externDtor
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         SigIndex:        0
+; CHECK-NEXT:       - Module:          env
+; CHECK-NEXT:         Field:           externCtor
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         SigIndex:        0
 ; CHECK:        - Type:            ELEM
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1
-; CHECK-NEXT:         Functions:       [ 6, 8, 12, 14, 16 ]
-
-; CHECK:              Body:            100010011007100A100D100A100F10001009100A10110B
+; CHECK-NEXT:         Functions:       [ 9, 11, 13, 17, 19, 21 ]
+; CHECK-NEXT:   - Type:            CODE
+; CHECK-NEXT:     Functions:
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            10031004100A100F1012100F10141003100C100F10161001100E0B
+; CHECK:            - Index:           22
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            024041868080800041004180888080001087808080000D000F0B00000B
 ; CHECK-NEXT:   - Type:            CUSTOM
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            func1
+; CHECK-NEXT:         Name:            externDtor
 ; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            func2
+; CHECK-NEXT:         Name:            externCtor
 ; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Name:            func3
-; CHECK-NEXT:       - Index:           3
-; CHECK-NEXT:         Name:            func4
-; CHECK-NEXT:       - Index:           4
-; CHECK-NEXT:         Name:            __cxa_atexit
-; CHECK-NEXT:       - Index:           5
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           6
-; CHECK-NEXT:         Name:            .Lcall_dtors.101
-; CHECK-NEXT:       - Index:           7
-; CHECK-NEXT:         Name:            .Lregister_call_dtors.101
-; CHECK-NEXT:       - Index:           8
-; CHECK-NEXT:         Name:            .Lcall_dtors.1001
-; CHECK-NEXT:       - Index:           9
-; CHECK-NEXT:         Name:            .Lregister_call_dtors.1001
-; CHECK-NEXT:       - Index:           10
-; CHECK-NEXT:         Name:            myctor
-; CHECK-NEXT:       - Index:           11
-; CHECK-NEXT:         Name:            mydtor
-; CHECK-NEXT:       - Index:           12
-; CHECK-NEXT:         Name:            .Lcall_dtors.101
-; CHECK-NEXT:       - Index:           13
-; CHECK-NEXT:         Name:            .Lregister_call_dtors.101
-; CHECK-NEXT:       - Index:           14
-; CHECK-NEXT:         Name:            .Lcall_dtors.202
-; CHECK-NEXT:       - Index:           15
-; CHECK-NEXT:         Name:            .Lregister_call_dtors.202
-; CHECK-NEXT:       - Index:           16
-; CHECK-NEXT:         Name:            .Lcall_dtors.2002
-; CHECK-NEXT:       - Index:           17
-; CHECK-NEXT:         Name:            .Lregister_call_dtors.2002
-; CHECK-NEXT:       - Index:           18
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            func1
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Name:            func2
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Name:            func3
+; CHECK-NEXT:       - Index:           6
+; CHECK-NEXT:         Name:            func4
+; CHECK-NEXT:       - Index:           7
+; CHECK-NEXT:         Name:            __cxa_atexit
+; CHECK-NEXT:       - Index:           8
+; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT:       - Index:           9
+; CHECK-NEXT:         Name:            .Lcall_dtors.101
+; CHECK-NEXT:       - Index:           10
+; CHECK-NEXT:         Name:            .Lregister_call_dtors.101
+; CHECK-NEXT:       - Index:           11
+; CHECK-NEXT:         Name:            .Lcall_dtors.1001
+; CHECK-NEXT:       - Index:           12
+; CHECK-NEXT:         Name:            .Lregister_call_dtors.1001
+; CHECK-NEXT:       - Index:           13
+; CHECK-NEXT:         Name:            .Lcall_dtors.4000
+; CHECK-NEXT:       - Index:           14
+; CHECK-NEXT:         Name:            .Lregister_call_dtors.4000
+; CHECK-NEXT:       - Index:           15
+; CHECK-NEXT:         Name:            myctor
+; CHECK-NEXT:       - Index:           16
+; CHECK-NEXT:         Name:            mydtor
+; CHECK-NEXT:       - Index:           17
+; CHECK-NEXT:         Name:            .Lcall_dtors.101
+; CHECK-NEXT:       - Index:           18
+; CHECK-NEXT:         Name:            .Lregister_call_dtors.101
+; CHECK-NEXT:       - Index:           19
+; CHECK-NEXT:         Name:            .Lcall_dtors.202
+; CHECK-NEXT:       - Index:           20
+; CHECK-NEXT:         Name:            .Lregister_call_dtors.202
+; CHECK-NEXT:       - Index:           21
+; CHECK-NEXT:         Name:            .Lcall_dtors.2002
+; CHECK-NEXT:       - Index:           22
+; CHECK-NEXT:         Name:            .Lregister_call_dtors.2002
 ; CHECK-NEXT: ...
 
 
@@ -108,42 +137,42 @@
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            func1
 ; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
-; RELOC-NEXT:         Function:        0
+; RELOC-NEXT:         Function:        2
 ; RELOC-NEXT:       - Index:           1
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            func2
 ; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
-; RELOC-NEXT:         Function:        1
+; RELOC-NEXT:         Function:        3
 ; RELOC-NEXT:       - Index:           2
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            func3
 ; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
-; RELOC-NEXT:         Function:        2
+; RELOC-NEXT:         Function:        4
 ; RELOC-NEXT:       - Index:           3
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            func4
 ; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
-; RELOC-NEXT:         Function:        3
+; RELOC-NEXT:         Function:        5
 ; RELOC-NEXT:       - Index:           4
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            __cxa_atexit
 ; RELOC-NEXT:         Flags:           [  ]
-; RELOC-NEXT:         Function:        4
+; RELOC-NEXT:         Function:        6
 ; RELOC-NEXT:       - Index:           5
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            _start
 ; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
-; RELOC-NEXT:         Function:        5
+; RELOC-NEXT:         Function:        7
 ; RELOC-NEXT:       - Index:           6
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            .Lcall_dtors.101
 ; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        6
+; RELOC-NEXT:         Function:        8
 ; RELOC-NEXT:       - Index:           7
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            .Lregister_call_dtors.101
 ; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        7
+; RELOC-NEXT:         Function:        9
 ; RELOC-NEXT:       - Index:           8
 ; RELOC-NEXT:         Kind:            DATA
 ; RELOC-NEXT:         Name:            __dso_handle
@@ -152,57 +181,77 @@
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            .Lcall_dtors.1001
 ; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        8
+; RELOC-NEXT:         Function:        10
 ; RELOC-NEXT:       - Index:           10
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            .Lregister_call_dtors.1001
 ; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        9
+; RELOC-NEXT:         Function:        11
 ; RELOC-NEXT:       - Index:           11
 ; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            .Lcall_dtors.4000
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:         Function:        12
+; RELOC-NEXT:       - Index:           12
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            externDtor
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN, UNDEFINED ]
+; RELOC-NEXT:         Function:        0
+; RELOC-NEXT:       - Index:           13
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.4000
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:         Function:        13
+; RELOC-NEXT:       - Index:           14
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            externCtor
+; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN, UNDEFINED ]
+; RELOC-NEXT:         Function:        1
+; RELOC-NEXT:       - Index:           15
+; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            myctor
 ; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
-; RELOC-NEXT:         Function:        10
-; RELOC-NEXT:       - Index:           12
+; RELOC-NEXT:         Function:        14
+; RELOC-NEXT:       - Index:           16
 ; RELOC-NEXT:         Kind:            FUNCTION
 ; RELOC-NEXT:         Name:            mydtor
 ; RELOC-NEXT:         Flags:           [ VISIBILITY_HIDDEN ]
-; RELOC-NEXT:         Function:        11
-; RELOC-NEXT:       - Index:           13
+; RELOC-NEXT:         Function:        15
+; RELOC-NEXT:       - Index:           17
 ; RELOC-NEXT:         Kind:            GLOBAL
 ; RELOC-NEXT:         Name:            __stack_pointer
 ; RELOC-NEXT:         Flags:           [ UNDEFINED ]
 ; RELOC-NEXT:         Global:          0
-; RELOC-NEXT:       - Index:           14
-; RELOC-NEXT:         Kind:            FUNCTION
-; RELOC-NEXT:         Name:            .Lcall_dtors.101
-; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        12
-; RELOC-NEXT:       - Index:           15
-; RELOC-NEXT:         Kind:            FUNCTION
-; RELOC-NEXT:         Name:            .Lregister_call_dtors.101
-; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        13
-; RELOC-NEXT:       - Index:           16
-; RELOC-NEXT:         Kind:            FUNCTION
-; RELOC-NEXT:         Name:            .Lcall_dtors.202
-; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        14
-; RELOC-NEXT:       - Index:           17
-; RELOC-NEXT:         Kind:            FUNCTION
-; RELOC-NEXT:         Name:            .Lregister_call_dtors.202
-; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
-; RELOC-NEXT:         Function:        15
 ; RELOC-NEXT:       - Index:           18
 ; RELOC-NEXT:         Kind:            FUNCTION
-; RELOC-NEXT:         Name:            .Lcall_dtors.2002
+; RELOC-NEXT:         Name:            .Lcall_dtors.101
 ; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
 ; RELOC-NEXT:         Function:        16
 ; RELOC-NEXT:       - Index:           19
 ; RELOC-NEXT:         Kind:            FUNCTION
-; RELOC-NEXT:         Name:            .Lregister_call_dtors.2002
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.101
 ; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
 ; RELOC-NEXT:         Function:        17
+; RELOC-NEXT:       - Index:           20
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            .Lcall_dtors.202
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:         Function:        18
+; RELOC-NEXT:       - Index:           21
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.202
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:         Function:        19
+; RELOC-NEXT:       - Index:           22
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            .Lcall_dtors.2002
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:         Function:        20
+; RELOC-NEXT:       - Index:           23
+; RELOC-NEXT:         Kind:            FUNCTION
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.2002
+; RELOC-NEXT:         Flags:           [ BINDING_LOCAL ]
+; RELOC-NEXT:         Function:        21
 ; RELOC-NEXT:     InitFunctions:
 ; RELOC-NEXT:       - Priority:        101
 ; RELOC-NEXT:         Symbol:          0
@@ -211,58 +260,70 @@
 ; RELOC-NEXT:       - Priority:        101
 ; RELOC-NEXT:         Symbol:          7
 ; RELOC-NEXT:       - Priority:        101
-; RELOC-NEXT:         Symbol:          11
+; RELOC-NEXT:         Symbol:          15
 ; RELOC-NEXT:       - Priority:        101
+; RELOC-NEXT:         Symbol:          19
+; RELOC-NEXT:       - Priority:        202
 ; RELOC-NEXT:         Symbol:          15
 ; RELOC-NEXT:       - Priority:        202
-; RELOC-NEXT:         Symbol:          11
-; RELOC-NEXT:       - Priority:        202
-; RELOC-NEXT:         Symbol:          17
+; RELOC-NEXT:         Symbol:          21
 ; RELOC-NEXT:       - Priority:        1001
 ; RELOC-NEXT:         Symbol:          0
 ; RELOC-NEXT:       - Priority:        1001
 ; RELOC-NEXT:         Symbol:          10
 ; RELOC-NEXT:       - Priority:        2002
-; RELOC-NEXT:         Symbol:          11
+; RELOC-NEXT:         Symbol:          15
 ; RELOC-NEXT:       - Priority:        2002
-; RELOC-NEXT:         Symbol:          19
+; RELOC-NEXT:         Symbol:          23
+; RELOC-NEXT:       - Priority:        4000
+; RELOC-NEXT:         Symbol:          14
+; RELOC-NEXT:       - Priority:        4000
+; RELOC-NEXT:         Symbol:          13
 ; RELOC-NEXT:   - Type:            CUSTOM
 ; RELOC-NEXT:     Name:            name
 ; RELOC-NEXT:     FunctionNames:
 ; RELOC-NEXT:       - Index:           0
-; RELOC-NEXT:         Name:            func1
+; RELOC-NEXT:         Name:            externDtor
 ; RELOC-NEXT:       - Index:           1
-; RELOC-NEXT:         Name:            func2
+; RELOC-NEXT:         Name:            externCtor
 ; RELOC-NEXT:       - Index:           2
-; RELOC-NEXT:         Name:            func3
+; RELOC-NEXT:         Name:            func1
 ; RELOC-NEXT:       - Index:           3
-; RELOC-NEXT:         Name:            func4
+; RELOC-NEXT:         Name:            func2
 ; RELOC-NEXT:       - Index:           4
-; RELOC-NEXT:         Name:            __cxa_atexit
+; RELOC-NEXT:         Name:            func3
 ; RELOC-NEXT:       - Index:           5
-; RELOC-NEXT:         Name:            _start
+; RELOC-NEXT:         Name:            func4
 ; RELOC-NEXT:       - Index:           6
-; RELOC-NEXT:         Name:            .Lcall_dtors.101
+; RELOC-NEXT:         Name:            __cxa_atexit
 ; RELOC-NEXT:       - Index:           7
-; RELOC-NEXT:         Name:            .Lregister_call_dtors.101
+; RELOC-NEXT:         Name:            _start
 ; RELOC-NEXT:       - Index:           8
-; RELOC-NEXT:         Name:            .Lcall_dtors.1001
-; RELOC-NEXT:       - Index:           9
-; RELOC-NEXT:         Name:            .Lregister_call_dtors.1001
-; RELOC-NEXT:       - Index:           10
-; RELOC-NEXT:         Name:            myctor
-; RELOC-NEXT:       - Index:           11
-; RELOC-NEXT:         Name:            mydtor
-; RELOC-NEXT:       - Index:           12
 ; RELOC-NEXT:         Name:            .Lcall_dtors.101
-; RELOC-NEXT:       - Index:           13
+; RELOC-NEXT:       - Index:           9
 ; RELOC-NEXT:         Name:            .Lregister_call_dtors.101
+; RELOC-NEXT:       - Index:           10
+; RELOC-NEXT:         Name:            .Lcall_dtors.1001
+; RELOC-NEXT:       - Index:           11
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.1001
+; RELOC-NEXT:       - Index:           12
+; RELOC-NEXT:         Name:            .Lcall_dtors.4000
+; RELOC-NEXT:       - Index:           13
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.4000
 ; RELOC-NEXT:       - Index:           14
-; RELOC-NEXT:         Name:            .Lcall_dtors.202
+; RELOC-NEXT:         Name:            myctor
 ; RELOC-NEXT:       - Index:           15
-; RELOC-NEXT:         Name:            .Lregister_call_dtors.202
+; RELOC-NEXT:         Name:            mydtor
 ; RELOC-NEXT:       - Index:           16
-; RELOC-NEXT:         Name:            .Lcall_dtors.2002
+; RELOC-NEXT:         Name:            .Lcall_dtors.101
 ; RELOC-NEXT:       - Index:           17
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.101
+; RELOC-NEXT:       - Index:           18
+; RELOC-NEXT:         Name:            .Lcall_dtors.202
+; RELOC-NEXT:       - Index:           19
+; RELOC-NEXT:         Name:            .Lregister_call_dtors.202
+; RELOC-NEXT:       - Index:           20
+; RELOC-NEXT:         Name:            .Lcall_dtors.2002
+; RELOC-NEXT:       - Index:           21
 ; RELOC-NEXT:         Name:            .Lregister_call_dtors.2002
 ; RELOC-NEXT: ...
diff --git a/test/wasm/load-undefined.test b/test/wasm/load-undefined.test
index 144ef28..7e78bf0 100644
--- a/test/wasm/load-undefined.test
+++ b/test/wasm/load-undefined.test
@@ -21,13 +21,13 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            ret32
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            ret64
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:   - Type:
 
 
diff --git a/test/wasm/local-symbols.ll b/test/wasm/local-symbols.ll
index 149ba03..fcb3c42 100644
--- a/test/wasm/local-symbols.ll
+++ b/test/wasm/local-symbols.ll
@@ -26,13 +26,13 @@
 ; CHECK-NEXT:   - Type:            TYPE
 ; CHECK-NEXT:     Signatures:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         ReturnType:      I32
-; CHECK-NEXT:         ParamTypes:
-; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         ReturnType:      NORESULT
 ; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 1 ]
+; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 0 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -82,7 +82,7 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            foo
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         Index:           3
@@ -90,13 +90,13 @@
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4100280284888080000B
+; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1080808080001A0B
+; CHECK-NEXT:         Body:            4100280284888080000B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:         Body:            1081808080001A0B
 ; CHECK-NEXT:   - Type:            DATA
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - SectionOffset:   7
@@ -109,9 +109,9 @@
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            baz
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            baz
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            _start
 ; CHECK-NEXT: ...
diff --git a/test/wasm/locals-duplicate.test b/test/wasm/locals-duplicate.test
index 0eee7b6..017bc09 100644
--- a/test/wasm/locals-duplicate.test
+++ b/test/wasm/locals-duplicate.test
@@ -10,14 +10,14 @@
 ; CHECK-NEXT:   - Type:            TYPE
 ; CHECK-NEXT:     Signatures:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         ReturnType:      I32
-; CHECK-NEXT:         ParamTypes:
-; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         ReturnType:      NORESULT
 ; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-; CHECK-NEXT:                        0, 0, 1 ]
+; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+; CHECK-NEXT:                        1, 1, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -73,63 +73,63 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            colliding_func2
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            get_global1A
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           3
+; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:       - Name:            get_global2A
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:         Index:           5
 ; CHECK-NEXT:       - Name:            colliding_global2
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            get_global3A
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           5
+; CHECK-NEXT:         Index:           6
 ; CHECK-NEXT:       - Name:            get_func1A
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           6
+; CHECK-NEXT:         Index:           7
 ; CHECK-NEXT:       - Name:            get_func2A
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           7
+; CHECK-NEXT:         Index:           8
 ; CHECK-NEXT:       - Name:            get_func3A
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           8
+; CHECK-NEXT:         Index:           9
 ; CHECK-NEXT:       - Name:            colliding_func1
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           9
+; CHECK-NEXT:         Index:           10
 ; CHECK-NEXT:       - Name:            get_global1B
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           12
+; CHECK-NEXT:         Index:           13
 ; CHECK-NEXT:       - Name:            colliding_global1
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:       - Name:            get_global2B
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           13
+; CHECK-NEXT:         Index:           14
 ; CHECK-NEXT:       - Name:            get_global3B
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           14
+; CHECK-NEXT:         Index:           15
 ; CHECK-NEXT:       - Name:            get_func1B
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           15
+; CHECK-NEXT:         Index:           16
 ; CHECK-NEXT:       - Name:            get_func2B
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           16
+; CHECK-NEXT:         Index:           17
 ; CHECK-NEXT:       - Name:            get_func3B
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           17
+; CHECK-NEXT:         Index:           18
 ; CHECK-NEXT:   - Type:            ELEM
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1
-; CHECK-NEXT:         Functions:       [ 0, 1, 2, 9, 10, 11 ]
+; CHECK-NEXT:         Functions:       [ 1, 2, 3, 10, 11, 12 ]
 ; CHECK-NEXT:   - Type:            CODE
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:         Body:            41020B
@@ -138,25 +138,25 @@
 ; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4180888080000B
+; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4184888080000B
+; CHECK-NEXT:         Body:            4180888080000B
 ; CHECK-NEXT:       - Index:           5
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4188888080000B
+; CHECK-NEXT:         Body:            4184888080000B
 ; CHECK-NEXT:       - Index:           6
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4181808080000B
+; CHECK-NEXT:         Body:            4188888080000B
 ; CHECK-NEXT:       - Index:           7
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4182808080000B
+; CHECK-NEXT:         Body:            4181808080000B
 ; CHECK-NEXT:       - Index:           8
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4183808080000B
+; CHECK-NEXT:         Body:            4182808080000B
 ; CHECK-NEXT:       - Index:           9
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:         Body:            4183808080000B
 ; CHECK-NEXT:       - Index:           10
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:         Body:            41020B
@@ -165,25 +165,25 @@
 ; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           12
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            418C888080000B
+; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           13
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4190888080000B
+; CHECK-NEXT:         Body:            418C888080000B
 ; CHECK-NEXT:       - Index:           14
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4194888080000B
+; CHECK-NEXT:         Body:            4190888080000B
 ; CHECK-NEXT:       - Index:           15
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4184808080000B
+; CHECK-NEXT:         Body:            4194888080000B
 ; CHECK-NEXT:       - Index:           16
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4185808080000B
+; CHECK-NEXT:         Body:            4184808080000B
 ; CHECK-NEXT:       - Index:           17
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4186808080000B
+; CHECK-NEXT:         Body:            4185808080000B
 ; CHECK-NEXT:       - Index:           18
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:         Body:            4186808080000B
 ; CHECK-NEXT:   - Type:            DATA
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - SectionOffset:   7
@@ -196,43 +196,43 @@
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            colliding_func1
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            colliding_func2
-; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Name:            colliding_func3
-; CHECK-NEXT:       - Index:           3
-; CHECK-NEXT:         Name:            get_global1A
-; CHECK-NEXT:       - Index:           4
-; CHECK-NEXT:         Name:            get_global2A
-; CHECK-NEXT:       - Index:           5
-; CHECK-NEXT:         Name:            get_global3A
-; CHECK-NEXT:       - Index:           6
-; CHECK-NEXT:         Name:            get_func1A
-; CHECK-NEXT:       - Index:           7
-; CHECK-NEXT:         Name:            get_func2A
-; CHECK-NEXT:       - Index:           8
-; CHECK-NEXT:         Name:            get_func3A
-; CHECK-NEXT:       - Index:           9
-; CHECK-NEXT:         Name:            colliding_func1
-; CHECK-NEXT:       - Index:           10
-; CHECK-NEXT:         Name:            colliding_func2
-; CHECK-NEXT:       - Index:           11
-; CHECK-NEXT:         Name:            colliding_func3
-; CHECK-NEXT:       - Index:           12
-; CHECK-NEXT:         Name:            get_global1B
-; CHECK-NEXT:       - Index:           13
-; CHECK-NEXT:         Name:            get_global2B
-; CHECK-NEXT:       - Index:           14
-; CHECK-NEXT:         Name:            get_global3B
-; CHECK-NEXT:       - Index:           15
-; CHECK-NEXT:         Name:            get_func1B
-; CHECK-NEXT:       - Index:           16
-; CHECK-NEXT:         Name:            get_func2B
-; CHECK-NEXT:       - Index:           17
-; CHECK-NEXT:         Name:            get_func3B
-; CHECK-NEXT:       - Index:           18
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            colliding_func1
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            colliding_func2
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            colliding_func3
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Name:            get_global1A
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Name:            get_global2A
+; CHECK-NEXT:       - Index:           6
+; CHECK-NEXT:         Name:            get_global3A
+; CHECK-NEXT:       - Index:           7
+; CHECK-NEXT:         Name:            get_func1A
+; CHECK-NEXT:       - Index:           8
+; CHECK-NEXT:         Name:            get_func2A
+; CHECK-NEXT:       - Index:           9
+; CHECK-NEXT:         Name:            get_func3A
+; CHECK-NEXT:       - Index:           10
+; CHECK-NEXT:         Name:            colliding_func1
+; CHECK-NEXT:       - Index:           11
+; CHECK-NEXT:         Name:            colliding_func2
+; CHECK-NEXT:       - Index:           12
+; CHECK-NEXT:         Name:            colliding_func3
+; CHECK-NEXT:       - Index:           13
+; CHECK-NEXT:         Name:            get_global1B
+; CHECK-NEXT:       - Index:           14
+; CHECK-NEXT:         Name:            get_global2B
+; CHECK-NEXT:       - Index:           15
+; CHECK-NEXT:         Name:            get_global3B
+; CHECK-NEXT:       - Index:           16
+; CHECK-NEXT:         Name:            get_func1B
+; CHECK-NEXT:       - Index:           17
+; CHECK-NEXT:         Name:            get_func2B
+; CHECK-NEXT:       - Index:           18
+; CHECK-NEXT:         Name:            get_func3B
 ; CHECK-NEXT: ...
 
 
diff --git a/test/wasm/undefined-weak-call.ll b/test/wasm/undefined-weak-call.ll
new file mode 100644
index 0000000..cd26e05
--- /dev/null
+++ b/test/wasm/undefined-weak-call.ll
@@ -0,0 +1,117 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: wasm-ld --check-signatures --no-entry %t.o -o %t.wasm
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; Check that calling an undefined weak function generates an appropriate stub
+; that will fail at runtime with "unreachable".
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+declare extern_weak void @weakFunc1()
+declare extern_weak void @weakFunc2()         ; same signature
+declare extern_weak void @weakFunc3(i32 %arg) ; different
+declare extern_weak void @weakFunc4()         ; should be GC'd as not called
+
+define i32 @callWeakFuncs() {
+  call void @weakFunc1()
+  call void @weakFunc2()
+  call void @weakFunc3(i32 2)
+  %addr1 = ptrtoint void ()* @weakFunc1 to i32
+  %addr4 = ptrtoint void ()* @weakFunc4 to i32
+  %sum = add i32 %addr1, %addr4
+  ret i32 %sum
+}
+
+; CHECK:      --- !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT:   Version:         0x00000001
+; CHECK-NEXT: Sections:
+; CHECK-NEXT:   - Type:            TYPE
+; CHECK-NEXT:     Signatures:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ReturnType:      NORESULT
+; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         ReturnType:      NORESULT
+; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:           - I32
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:   - Type:            FUNCTION
+; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 0, 1, 2 ]
+; CHECK-NEXT:   - Type:            TABLE
+; CHECK-NEXT:     Tables:
+; CHECK-NEXT:       - ElemType:        ANYFUNC
+; CHECK-NEXT:         Limits:
+; CHECK-NEXT:           Flags:           [ HAS_MAX ]
+; CHECK-NEXT:           Initial:         0x00000001
+; CHECK-NEXT:           Maximum:         0x00000001
+; CHECK-NEXT:   - Type:            MEMORY
+; CHECK-NEXT:     Memories:
+; CHECK-NEXT:       - Initial:         0x00000002
+; CHECK-NEXT:   - Type:            GLOBAL
+; CHECK-NEXT:     Globals:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Type:            I32
+; CHECK-NEXT:         Mutable:         true
+; CHECK-NEXT:         InitExpr:
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           66560
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Type:            I32
+; CHECK-NEXT:         Mutable:         false
+; CHECK-NEXT:         InitExpr:
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           66560
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Type:            I32
+; CHECK-NEXT:         Mutable:         false
+; CHECK-NEXT:         InitExpr:
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           1024
+; CHECK-NEXT:   - Type:            EXPORT
+; CHECK-NEXT:     Exports:
+; CHECK-NEXT:       - Name:            memory
+; CHECK-NEXT:         Kind:            MEMORY
+; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:       - Name:            __heap_base
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:       - Name:            __data_end
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:       - Name:            callWeakFuncs
+; CHECK-NEXT:         Kind:            FUNCTION
+; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:   - Type:            CODE
+; CHECK-NEXT:     Functions:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            000B
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            000B
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            000B
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Locals:
+; CHECK-NEXT:         Body:            10818080800010828080800041021083808080004180808080004180808080006A0B
+; CHECK-NEXT:   - Type:            CUSTOM
+; CHECK-NEXT:     Name:            name
+; CHECK-NEXT:     FunctionNames:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            undefined function weakFunc1
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            undefined function weakFunc2
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            undefined function weakFunc3
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Name:            callWeakFuncs
+; CHECK-NEXT: ...
diff --git a/test/wasm/undefined.ll b/test/wasm/undefined.ll
index 69b7a82..a74dd6d 100644
--- a/test/wasm/undefined.ll
+++ b/test/wasm/undefined.ll
@@ -6,10 +6,13 @@
 ; CHECK: error: {{.*}}.o: undefined symbol: foo
 ; CHECK: error: undefined symbol: baz
 
-; But succeeds if we pass a file containing 'foo' as --allow-undefined-file.
+; Succeeds if we pass a file containing 'foo' as --allow-undefined-file.
 ; RUN: echo 'foo' > %t.txt
 ; RUN: wasm-ld --check-signatures --allow-undefined-file=%t.txt -o %t.wasm %t.o
 
+; Succeeds even if a missing symbol is added via --export
+; RUN: wasm-ld --check-signatures --allow-undefined --export=xxx -o %t.wasm %t.o
+
 target triple = "wasm32-unknown-unknown-wasm"
 
 ; Takes the address of the external foo() resulting in undefined external
diff --git a/test/wasm/visibility-hidden.ll b/test/wasm/visibility-hidden.ll
index 38db22f..530649b 100644
--- a/test/wasm/visibility-hidden.ll
+++ b/test/wasm/visibility-hidden.ll
@@ -44,11 +44,11 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            objectDefault
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            archiveDefault
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:         Index:           5
 ; CHECK-NEXT:   - Type:
diff --git a/test/wasm/weak-alias-overide.ll b/test/wasm/weak-alias-overide.ll
index b4f8361..2252298 100644
--- a/test/wasm/weak-alias-overide.ll
+++ b/test/wasm/weak-alias-overide.ll
@@ -26,13 +26,13 @@
 ; CHECK-NEXT:   - Type:            TYPE
 ; CHECK-NEXT:     Signatures:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         ReturnType:      I32
-; CHECK-NEXT:         ParamTypes:
-; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         ReturnType:      NORESULT
 ; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 0, 0, 0, 0, 0, 1 ]
+; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 0, 1, 1, 1, 1, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -76,78 +76,78 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            alias_fn
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            direct_fn
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            call_direct
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           3
+; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:       - Name:            call_alias
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:         Index:           5
 ; CHECK-NEXT:       - Name:            call_alias_ptr
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           5
+; CHECK-NEXT:         Index:           6
 ; CHECK-NEXT:       - Name:            call_direct_ptr
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           6
+; CHECK-NEXT:         Index:           7
 ; CHECK-NEXT:   - Type:            ELEM
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1
-; CHECK-NEXT:         Functions:       [ 0, 2 ]
+; CHECK-NEXT:         Functions:       [ 1, 3 ]
 ; CHECK-NEXT:   - Type:            CODE
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41010B
+; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1080808080001A0B
+; CHECK-NEXT:         Body:            41010B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41000B
+; CHECK-NEXT:         Body:            1081808080001A0B
 ; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1082808080000B
+; CHECK-NEXT:         Body:            41000B
 ; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1080808080000B
+; CHECK-NEXT:         Body:            1083808080000B
 ; CHECK-NEXT:       - Index:           5
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:           - Type:            I32
-; CHECK-NEXT:             Count:           2
-; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004181808080003602081080808080002101200041106A24808080800020010B
+; CHECK-NEXT:         Body:            1081808080000B
 ; CHECK-NEXT:       - Index:           6
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:           - Type:            I32
 ; CHECK-NEXT:             Count:           2
-; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004182808080003602081082808080002101200041106A24808080800020010B
+; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B
 ; CHECK-NEXT:       - Index:           7
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:           - Type:            I32
+; CHECK-NEXT:             Count:           2
+; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004182808080003602081083808080002101200041106A24808080800020010B
 ; CHECK-NEXT:   - Type:            CUSTOM
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            alias_fn
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Name:            direct_fn
-; CHECK-NEXT:       - Index:           3
-; CHECK-NEXT:         Name:            call_direct
-; CHECK-NEXT:       - Index:           4
-; CHECK-NEXT:         Name:            call_alias
-; CHECK-NEXT:       - Index:           5
-; CHECK-NEXT:         Name:            call_alias_ptr
-; CHECK-NEXT:       - Index:           6
-; CHECK-NEXT:         Name:            call_direct_ptr
-; CHECK-NEXT:       - Index:           7
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            alias_fn
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            direct_fn
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Name:            call_direct
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Name:            call_alias
+; CHECK-NEXT:       - Index:           6
+; CHECK-NEXT:         Name:            call_alias_ptr
+; CHECK-NEXT:       - Index:           7
+; CHECK-NEXT:         Name:            call_direct_ptr
 ; CHECK-NEXT: ...
diff --git a/test/wasm/weak-alias.ll b/test/wasm/weak-alias.ll
index a71c2ea..1df16e2 100644
--- a/test/wasm/weak-alias.ll
+++ b/test/wasm/weak-alias.ll
@@ -29,7 +29,7 @@
 ; CHECK-NEXT:         ReturnType:      I32
 ; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 1, 1, 1, 1, 0 ]
+; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 1, 1, 1, 1, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -73,75 +73,75 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            alias_fn
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            direct_fn
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            call_direct
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            call_alias
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           3
+; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:       - Name:            call_alias_ptr
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:         Index:           5
 ; CHECK-NEXT:       - Name:            call_direct_ptr
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           5
+; CHECK-NEXT:         Index:           6
 ; CHECK-NEXT:   - Type:            ELEM
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1
-; CHECK-NEXT:         Functions:       [ 1 ]
+; CHECK-NEXT:         Functions:       [ 2 ]
 ; CHECK-NEXT:   - Type:            CODE
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1081808080001A0B
+; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41000B
+; CHECK-NEXT:         Body:            1082808080001A0B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1081808080000B
+; CHECK-NEXT:         Body:            41000B
 ; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1081808080000B
+; CHECK-NEXT:         Body:            1082808080000B
 ; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:           - Type:            I32
-; CHECK-NEXT:             Count:           2
-; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B
+; CHECK-NEXT:         Body:            1082808080000B
 ; CHECK-NEXT:       - Index:           5
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:           - Type:            I32
 ; CHECK-NEXT:             Count:           2
-; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B
+; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004181808080003602081082808080002101200041106A24808080800020010B
 ; CHECK-NEXT:       - Index:           6
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:           - Type:            I32
+; CHECK-NEXT:             Count:           2
+; CHECK-NEXT:         Body:            23808080800041106B220024808080800020004181808080003602081082808080002101200041106A24808080800020010B
 ; CHECK-NEXT:   - Type:            CUSTOM
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            direct_fn
-; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Name:            call_direct
-; CHECK-NEXT:       - Index:           3
-; CHECK-NEXT:         Name:            call_alias
-; CHECK-NEXT:       - Index:           4
-; CHECK-NEXT:         Name:            call_alias_ptr
-; CHECK-NEXT:       - Index:           5
-; CHECK-NEXT:         Name:            call_direct_ptr
-; CHECK-NEXT:       - Index:           6
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            direct_fn
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            call_direct
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Name:            call_alias
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Name:            call_alias_ptr
+; CHECK-NEXT:       - Index:           6
+; CHECK-NEXT:         Name:            call_direct_ptr
 ; CHECK-NEXT: ...
 
 ; RUN: wasm-ld --check-signatures --relocatable %t.o %t2.o -o %t.reloc.o
diff --git a/test/wasm/weak-symbols.ll b/test/wasm/weak-symbols.ll
index 9724e81..7ecb900 100644
--- a/test/wasm/weak-symbols.ll
+++ b/test/wasm/weak-symbols.ll
@@ -29,7 +29,7 @@
 ; CHECK-NEXT:         ReturnType:      I32
 ; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 1, 1, 1, 0 ]
+; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 1, 1, 1, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -79,45 +79,45 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            weakFn
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            exportWeak1
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            weakGlobal
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            exportWeak2
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           4
+; CHECK-NEXT:         Index:           5
 ; CHECK-NEXT:   - Type:            ELEM
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1
-; CHECK-NEXT:         Functions:       [ 1 ]
+; CHECK-NEXT:         Functions:       [ 2 ]
 ; CHECK-NEXT:   - Type:            CODE
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1081808080001A0B
+; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41010B
+; CHECK-NEXT:         Body:            1082808080001A0B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4181808080000B
+; CHECK-NEXT:         Body:            41010B
 ; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41020B
+; CHECK-NEXT:         Body:            4181808080000B
 ; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4181808080000B
+; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           5
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:         Body:            4181808080000B
 ; CHECK-NEXT:   - Type:            DATA
 ; CHECK-NEXT:     Segments:
 ; CHECK-NEXT:       - SectionOffset:   7
@@ -130,15 +130,15 @@
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            _start
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Name:            weakFn
-; CHECK-NEXT:       - Index:           2
-; CHECK-NEXT:         Name:            exportWeak1
-; CHECK-NEXT:       - Index:           3
-; CHECK-NEXT:         Name:            weakFn
-; CHECK-NEXT:       - Index:           4
-; CHECK-NEXT:         Name:            exportWeak2
-; CHECK-NEXT:       - Index:           5
 ; CHECK-NEXT:         Name:            __wasm_call_ctors
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Name:            _start
+; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         Name:            weakFn
+; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:         Name:            exportWeak1
+; CHECK-NEXT:       - Index:           4
+; CHECK-NEXT:         Name:            weakFn
+; CHECK-NEXT:       - Index:           5
+; CHECK-NEXT:         Name:            exportWeak2
 ; CHECK-NEXT: ...
diff --git a/test/wasm/weak-undefined.ll b/test/wasm/weak-undefined.ll
index 6de571f..ce68e54 100644
--- a/test/wasm/weak-undefined.ll
+++ b/test/wasm/weak-undefined.ll
@@ -33,13 +33,13 @@
 ; CHECK-NEXT:   - Type:            TYPE
 ; CHECK-NEXT:     Signatures:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         ReturnType:      I32
-; CHECK-NEXT:         ParamTypes:
-; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         ReturnType:      NORESULT
 ; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 1, 1 ]
+; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 1, 0 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -83,25 +83,25 @@
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:       - Name:            _start
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:         Index:           3
 ; CHECK-NEXT:       - Name:            get_address_of_foo
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            get_address_of_global_var
 ; CHECK-NEXT:         Kind:            FUNCTION
-; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:   - Type:            CODE
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            4180808080000B
+; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:         Body:            4180808080000B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            1081808080001A0B
+; CHECK-NEXT:         Body:            4180808080000B
 ; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:         Body:            1082808080001A0B
 ; CHECK-NEXT: ...
diff --git a/wasm/Config.h b/wasm/Config.h
index b6db524..adccbfe 100644
--- a/wasm/Config.h
+++ b/wasm/Config.h
@@ -21,8 +21,10 @@
   bool AllowUndefined;
   bool CheckSignatures;
   bool Demangle;
+  bool ExportTable;
   bool GcSections;
   bool ImportMemory;
+  bool ImportTable;
   bool PrintGcSections;
   bool Relocatable;
   bool StripAll;
diff --git a/wasm/Driver.cpp b/wasm/Driver.cpp
index e68a7ce..97a8159 100644
--- a/wasm/Driver.cpp
+++ b/wasm/Driver.cpp
@@ -9,6 +9,7 @@
 
 #include "lld/Common/Driver.h"
 #include "Config.h"
+#include "InputChunks.h"
 #include "InputGlobal.h"
 #include "MarkLive.h"
 #include "SymbolTable.h"
@@ -16,6 +17,7 @@
 #include "lld/Common/Args.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
 #include "lld/Common/Threads.h"
 #include "lld/Common/Version.h"
 #include "llvm/ADT/Twine.h"
@@ -214,6 +216,46 @@
   return Arg->getValue();
 }
 
+static const uint8_t UnreachableFn[] = {
+    0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
+    0x00 /* opcode unreachable */, 0x0b /* opcode end */
+};
+
+// For weak undefined functions, there may be "call" instructions that reference
+// the symbol. In this case, we need to synthesise a dummy/stub function that
+// will abort at runtime, so that relocations can still provided an operand to
+// the call instruction that passes Wasm validation.
+static void handleWeakUndefines() {
+  for (Symbol *Sym : Symtab->getSymbols()) {
+    if (!Sym->isUndefined() || !Sym->isWeak())
+      continue;
+    auto *FuncSym = dyn_cast<FunctionSymbol>(Sym);
+    if (!FuncSym)
+      continue;
+
+    // It is possible for undefined functions not to have a signature (eg. if
+    // added via "--undefined"), but weak undefined ones do have a signature.
+    assert(FuncSym->getFunctionType());
+    const WasmSignature &Sig = *FuncSym->getFunctionType();
+
+    // Add a synthetic dummy for weak undefined functions.  These dummies will
+    // be GC'd if not used as the target of any "call" instructions.
+    Optional<std::string> SymName = demangleItanium(Sym->getName());
+    StringRef StubName =
+        Saver.save("undefined function " +
+                   (SymName ? StringRef(*SymName) : Sym->getName()));
+    SyntheticFunction *Func = make<SyntheticFunction>(Sig, StubName);
+    Func->setBody(UnreachableFn);
+    // Ensure it compares equal to the null pointer, and so that table relocs
+    // don't pull in the stub body (only call-operand relocs should do that).
+    Func->setTableIndex(0);
+    Symtab->SyntheticFunctions.emplace_back(Func);
+    // Hide our dummy to prevent export.
+    uint32_t Flags = WASM_SYMBOL_VISIBILITY_HIDDEN;
+    replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Flags, nullptr, Func);
+  }
+}
+
 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
   WasmOptTable Parser;
   opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
@@ -242,8 +284,11 @@
   Config->AllowUndefined = Args.hasArg(OPT_allow_undefined);
   Config->CheckSignatures =
       Args.hasFlag(OPT_check_signatures, OPT_no_check_signatures, false);
+  Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
   Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start");
+  Config->ExportTable = Args.hasArg(OPT_export_table);
   Config->ImportMemory = Args.hasArg(OPT_import_memory);
+  Config->ImportTable = Args.hasArg(OPT_import_table);
   Config->OutputFile = Args.getLastArgValue(OPT_o);
   Config->Relocatable = Args.hasArg(OPT_relocatable);
   Config->GcSections =
@@ -273,6 +318,9 @@
   if (Config->OutputFile.empty())
     error("no output file specified");
 
+  if (Config->ImportTable && Config->ExportTable)
+    error("--import-table and --export-table may not be used together");
+
   if (Config->Relocatable) {
     if (!Config->Entry.empty())
       error("entry point specified for relocatable output file");
@@ -295,9 +343,11 @@
     StackPointer->Live = true;
 
     static WasmSignature NullSignature = {{}, WASM_TYPE_NORESULT};
+
     // Add synthetic symbols before any others
     WasmSym::CallCtors = Symtab->addSyntheticFunction(
-        "__wasm_call_ctors", &NullSignature, WASM_SYMBOL_VISIBILITY_HIDDEN);
+        "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
+        make<SyntheticFunction>(NullSignature, "__wasm_call_ctors"));
     WasmSym::StackPointer = Symtab->addSyntheticGlobal(
         "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer);
     WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0);
@@ -310,7 +360,7 @@
                                               &NullSignature);
 
     // Handle the `--undefined <sym>` options.
-    for (auto* Arg : Args.filtered(OPT_undefined))
+    for (auto *Arg : Args.filtered(OPT_undefined))
       Symtab->addUndefinedFunction(Arg->getValue(), 0, nullptr, nullptr);
   }
 
@@ -323,6 +373,10 @@
   for (InputFile *F : Files)
     Symtab->addFile(F);
 
+  // Add synthetic dummies for weak undefined functions.
+  if (!Config->Relocatable)
+    handleWeakUndefines();
+
   // Make sure we have resolved all symbols.
   if (!Config->Relocatable && !Config->AllowUndefined) {
     Symtab->reportRemainingUndefines();
@@ -331,7 +385,7 @@
     // -u/--undefined since these undefined symbols have only names and no
     // function signature, which means they cannot be written to the final
     // output.
-    for (auto* Arg : Args.filtered(OPT_undefined)) {
+    for (auto *Arg : Args.filtered(OPT_undefined)) {
       Symbol *Sym = Symtab->find(Arg->getValue());
       if (!Sym->isDefined())
         error("function forced with --undefined not found: " + Sym->getName());
@@ -346,7 +400,7 @@
     Symbol *Sym = Symtab->find(Name);
     if (Sym && Sym->isDefined())
       Sym->setHidden(false);
-    else
+    else if (!Config->AllowUndefined)
       error("symbol exported via --export not found: " + Name);
   }
 
diff --git a/wasm/InputChunks.cpp b/wasm/InputChunks.cpp
index 546fb51..0cac19b 100644
--- a/wasm/InputChunks.cpp
+++ b/wasm/InputChunks.cpp
@@ -23,10 +23,26 @@
 using namespace lld;
 using namespace lld::wasm;
 
+StringRef ReloctTypeToString(uint8_t RelocType) {
+  switch (RelocType) {
+#define WASM_RELOC(NAME, REL) case REL: return #NAME;
+#include "llvm/BinaryFormat/WasmRelocs.def"
+#undef WASM_RELOC
+  }
+  llvm_unreachable("unknown reloc type");
+}
+
 std::string lld::toString(const InputChunk *C) {
   return (toString(C->File) + ":(" + C->getName() + ")").str();
 }
 
+StringRef InputChunk::getComdatName() const {
+  uint32_t Index = getComdat();
+  if (Index == UINT32_MAX)
+    return StringRef();
+  return File->getWasmObj()->linkingData().Comdats[Index];
+}
+
 void InputChunk::copyRelocations(const WasmSection &Section) {
   if (Section.Relocations.empty())
     return;
@@ -46,14 +62,16 @@
   if (Relocations.empty())
     return;
 
-  DEBUG(dbgs() << "applyRelocations: count=" << Relocations.size() << "\n");
+  DEBUG(dbgs() << "applying relocations: " << getName()
+               << " count=" << Relocations.size() << "\n");
   int32_t Off = OutputOffset - getInputSectionOffset();
 
   for (const WasmRelocation &Rel : Relocations) {
     uint8_t *Loc = Buf + Rel.Offset + Off;
-    uint64_t Value = File->calcNewValue(Rel);
-
-    DEBUG(dbgs() << "write reloc: type=" << Rel.Type << " index=" << Rel.Index
+    uint32_t Value = File->calcNewValue(Rel);
+    uint32_t ExistingValue;
+    DEBUG(dbgs() << "apply reloc: type=" << ReloctTypeToString(Rel.Type)
+                 << " addend=" << Rel.Addend << " index=" << Rel.Index
                  << " value=" << Value << " offset=" << Rel.Offset << "\n");
 
     switch (Rel.Type) {
@@ -61,19 +79,28 @@
     case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
     case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
     case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+      ExistingValue = decodeULEB128(Loc);
       encodeULEB128(Value, Loc, 5);
       break;
     case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
     case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+      ExistingValue = static_cast<uint32_t>(decodeSLEB128(Loc));
       encodeSLEB128(static_cast<int32_t>(Value), Loc, 5);
       break;
     case R_WEBASSEMBLY_TABLE_INDEX_I32:
     case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+      ExistingValue = static_cast<uint32_t>(read32le(Loc));
       write32le(Loc, Value);
       break;
     default:
       llvm_unreachable("unknown relocation type");
     }
+
+    uint32_t ExpectedValue = File->calcExpectedValue(Rel);
+    if (ExpectedValue != ExistingValue)
+      error("unexpected existing value for " + ReloctTypeToString(Rel.Type) +
+            ": existing=" + Twine(ExistingValue) +
+            " expected=" + Twine(ExpectedValue));
   }
 }
 
@@ -103,14 +130,16 @@
   }
 }
 
-void InputFunction::setOutputIndex(uint32_t Index) {
-  DEBUG(dbgs() << "InputFunction::setOutputIndex: " << getName() << " -> " << Index << "\n");
-  assert(!hasOutputIndex());
-  OutputIndex = Index;
+void InputFunction::setFunctionIndex(uint32_t Index) {
+  DEBUG(dbgs() << "InputFunction::setFunctionIndex: " << getName() << " -> "
+               << Index << "\n");
+  assert(!hasFunctionIndex());
+  FunctionIndex = Index;
 }
 
 void InputFunction::setTableIndex(uint32_t Index) {
-  DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> " << Index << "\n");
+  DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> "
+               << Index << "\n");
   assert(!hasTableIndex());
   TableIndex = Index;
 }
diff --git a/wasm/InputChunks.h b/wasm/InputChunks.h
index bff574b..3d6ea23 100644
--- a/wasm/InputChunks.h
+++ b/wasm/InputChunks.h
@@ -24,14 +24,13 @@
 #include "Config.h"
 #include "InputFiles.h"
 #include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Strings.h"
 #include "llvm/Object/Wasm.h"
 
+using llvm::object::WasmSection;
 using llvm::object::WasmSegment;
 using llvm::wasm::WasmFunction;
 using llvm::wasm::WasmRelocation;
 using llvm::wasm::WasmSignature;
-using llvm::object::WasmSection;
 
 namespace llvm {
 class raw_ostream;
@@ -45,7 +44,7 @@
 
 class InputChunk {
 public:
-  enum Kind { DataSegment, Function };
+  enum Kind { DataSegment, Function, SyntheticFunction };
 
   Kind kind() const { return SectionKind; }
 
@@ -57,8 +56,9 @@
 
   ArrayRef<WasmRelocation> getRelocations() const { return Relocations; }
 
-  virtual StringRef getComdat() const = 0;
   virtual StringRef getName() const = 0;
+  virtual uint32_t getComdat() const = 0;
+  StringRef getComdatName() const;
 
   size_t NumRelocations() const { return Relocations.size(); }
   void writeRelocations(llvm::raw_ostream &OS) const;
@@ -99,7 +99,7 @@
 
   uint32_t getAlignment() const { return Segment.Data.Alignment; }
   StringRef getName() const override { return Segment.Data.Name; }
-  StringRef getComdat() const override { return Segment.Data.Comdat; }
+  uint32_t getComdat() const override { return Segment.Data.Comdat; }
 
   const OutputSegment *OutputSeg = nullptr;
   int32_t OutputSegmentOffset = 0;
@@ -117,19 +117,19 @@
 // combined to create the final output CODE section.
 class InputFunction : public InputChunk {
 public:
-  InputFunction(const WasmSignature &S, const WasmFunction *Func,
-                ObjFile *F)
+  InputFunction(const WasmSignature &S, const WasmFunction *Func, ObjFile *F)
       : InputChunk(F, InputChunk::Function), Signature(S), Function(Func) {}
 
   static bool classof(const InputChunk *C) {
-    return C->kind() == InputChunk::Function;
+    return C->kind() == InputChunk::Function ||
+           C->kind() == InputChunk::SyntheticFunction;
   }
 
   StringRef getName() const override { return Function->Name; }
-  StringRef getComdat() const override { return Function->Comdat; }
-  uint32_t getOutputIndex() const { return OutputIndex.getValue(); }
-  bool hasOutputIndex() const { return OutputIndex.hasValue(); }
-  void setOutputIndex(uint32_t Index);
+  uint32_t getComdat() const override { return Function->Comdat; }
+  uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); }
+  bool hasFunctionIndex() const { return FunctionIndex.hasValue(); }
+  void setFunctionIndex(uint32_t Index);
   uint32_t getTableIndex() const { return TableIndex.getValue(); }
   bool hasTableIndex() const { return TableIndex.hasValue(); }
   void setTableIndex(uint32_t Index);
@@ -146,22 +146,31 @@
   }
 
   const WasmFunction *Function;
-  llvm::Optional<uint32_t> OutputIndex;
+  llvm::Optional<uint32_t> FunctionIndex;
   llvm::Optional<uint32_t> TableIndex;
 };
 
 class SyntheticFunction : public InputFunction {
 public:
-  SyntheticFunction(const WasmSignature &S, std::string Body, StringRef Name)
-      : InputFunction(S, nullptr, nullptr), Name(Name), Body(std::move(Body)) {}
+  SyntheticFunction(const WasmSignature &S, StringRef Name)
+      : InputFunction(S, nullptr, nullptr), Name(Name) {
+    SectionKind = InputChunk::SyntheticFunction;
+  }
+
+  static bool classof(const InputChunk *C) {
+    return C->kind() == InputChunk::SyntheticFunction;
+  }
 
   StringRef getName() const override { return Name; }
+  uint32_t getComdat() const override { return UINT32_MAX; }
+
+  void setBody(ArrayRef<uint8_t> Body_) { Body = Body_; }
 
 protected:
-  ArrayRef<uint8_t> data() const override { return toArrayRef(Body); }
+  ArrayRef<uint8_t> data() const override { return Body; }
 
   StringRef Name;
-  std::string Body;
+  ArrayRef<uint8_t> Body;
 };
 
 } // namespace wasm
diff --git a/wasm/InputFiles.cpp b/wasm/InputFiles.cpp
index 2c65c7b..e743686 100644
--- a/wasm/InputFiles.cpp
+++ b/wasm/InputFiles.cpp
@@ -49,10 +49,9 @@
       "\n       Global Imports : " + Twine(WasmObj->getNumImportedGlobals()));
 }
 
-// Relocations contain an index into the function, global or table index
-// space of the input file.  This function takes a relocation and returns the
-// relocated index (i.e. translates from the input index space to the output
-// index space).
+// Relocations contain either symbol or type indices.  This function takes a
+// relocation and returns relocated index (i.e. translates from the input
+// sybmol/type space to the output symbol/type space).
 uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
   if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) {
     assert(TypeIsUsed[Reloc.Index]);
@@ -61,30 +60,56 @@
   return Symbols[Reloc.Index]->getOutputSymbolIndex();
 }
 
+// Calculate the value we expect to find at the relocation location.
+// This is used as a sanity check before applying a relocation to a given
+// location.  It is useful for catching bugs in the compiler and linker.
+uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {
+  switch (Reloc.Type) {
+  case R_WEBASSEMBLY_TABLE_INDEX_I32:
+  case R_WEBASSEMBLY_TABLE_INDEX_SLEB: {
+    const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
+    return TableEntries[Sym.Info.ElementIndex];
+  }
+  case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+  case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+  case R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
+    const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
+    if (Sym.isUndefined())
+      return 0;
+    const WasmSegment& Segment = WasmObj->dataSegments()[Sym.Info.DataRef.Segment];
+    return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset +
+           Reloc.Addend;
+  }
+  case R_WEBASSEMBLY_TYPE_INDEX_LEB:
+    return Reloc.Index;
+  case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+  case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
+    const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
+    return Sym.Info.ElementIndex;
+  }
+  default:
+    llvm_unreachable("unknown relocation type");
+  }
+}
+
 // Translate from the relocation's index into the final linked output value.
 uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
   switch (Reloc.Type) {
   case R_WEBASSEMBLY_TABLE_INDEX_I32:
-  case R_WEBASSEMBLY_TABLE_INDEX_SLEB: {
-    // The null case is possible, if you take the address of a weak function
-    // that's simply not supplied.
-    FunctionSymbol *Sym = getFunctionSymbol(Reloc.Index);
-    if (Sym->hasTableIndex())
-      return Sym->getTableIndex();
-    return 0;
-  }
+  case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+    return getFunctionSymbol(Reloc.Index)->getTableIndex();
   case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
   case R_WEBASSEMBLY_MEMORY_ADDR_I32:
   case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
     if (auto *Sym = dyn_cast<DefinedData>(getDataSymbol(Reloc.Index)))
       return Sym->getVirtualAddress() + Reloc.Addend;
-    return Reloc.Addend;
+    return 0;
   case R_WEBASSEMBLY_TYPE_INDEX_LEB:
     return TypeMap[Reloc.Index];
   case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
-    return getFunctionSymbol(Reloc.Index)->getOutputIndex();
+    return getFunctionSymbol(Reloc.Index)->getFunctionIndex();
   case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
-    return getGlobalSymbol(Reloc.Index)->getOutputIndex();
+    return getGlobalSymbol(Reloc.Index)->getGlobalIndex();
   default:
     llvm_unreachable("unknown relocation type");
   }
@@ -104,6 +129,22 @@
   Bin.release();
   WasmObj.reset(Obj);
 
+  // Build up a map of function indices to table indices for use when
+  // verifying the existing table index relocations
+  uint32_t TotalFunctions =
+      WasmObj->getNumImportedFunctions() + WasmObj->functions().size();
+  TableEntries.resize(TotalFunctions);
+  for (const WasmElemSegment &Seg : WasmObj->elements()) {
+    if (Seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
+      fatal(toString(this) + ": invalid table elements");
+    uint32_t Offset = Seg.Offset.Value.Int32;
+    for (uint32_t Index = 0; Index < Seg.Functions.size(); Index++) {
+
+      uint32_t FunctionIndex = Seg.Functions[Index];
+      TableEntries[FunctionIndex] = Offset + Index;
+    }
+  }
+
   // Find the code and data sections.  Wasm objects can have at most one code
   // and one data section.
   for (const SectionRef &Sec : WasmObj->sections()) {
@@ -117,6 +158,11 @@
   TypeMap.resize(getWasmObj()->types().size());
   TypeIsUsed.resize(getWasmObj()->types().size(), false);
 
+  ArrayRef<StringRef> Comdats = WasmObj->linkingData().Comdats;
+  UsedComdats.resize(Comdats.size());
+  for (unsigned I = 0; I < Comdats.size(); ++I)
+    UsedComdats[I] = Symtab->addComdat(Comdats[I]);
+
   // Populate `Segments`.
   for (const WasmSegment &S : WasmObj->dataSegments()) {
     InputSegment *Seg = make<InputSegment>(S, this);
@@ -153,10 +199,10 @@
 }
 
 bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const {
-  StringRef S = Chunk->getComdat();
-  if (S.empty())
+  uint32_t C = Chunk->getComdat();
+  if (C == UINT32_MAX)
     return false;
-  return !Symtab->addComdat(S, this);
+  return !UsedComdats[C];
 }
 
 FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
diff --git a/wasm/InputFiles.h b/wasm/InputFiles.h
index 97d41d8..f0fd267 100644
--- a/wasm/InputFiles.h
+++ b/wasm/InputFiles.h
@@ -25,8 +25,8 @@
 using llvm::object::WasmSymbol;
 using llvm::wasm::WasmGlobal;
 using llvm::wasm::WasmImport;
-using llvm::wasm::WasmSignature;
 using llvm::wasm::WasmRelocation;
+using llvm::wasm::WasmSignature;
 
 namespace lld {
 namespace wasm {
@@ -94,12 +94,17 @@
 
   uint32_t calcNewIndex(const WasmRelocation &Reloc) const;
   uint32_t calcNewValue(const WasmRelocation &Reloc) const;
+  uint32_t calcExpectedValue(const WasmRelocation &Reloc) const;
 
   const WasmSection *CodeSection = nullptr;
   const WasmSection *DataSection = nullptr;
 
+  // Maps input type indices to output type indices
   std::vector<uint32_t> TypeMap;
   std::vector<bool> TypeIsUsed;
+  // Maps function indices to table indices
+  std::vector<uint32_t> TableEntries;
+  std::vector<bool> UsedComdats;
   std::vector<InputSegment *> Segments;
   std::vector<InputFunction *> Functions;
   std::vector<InputGlobal *> Globals;
diff --git a/wasm/InputGlobal.h b/wasm/InputGlobal.h
index 53af220..16a6b7d 100644
--- a/wasm/InputGlobal.h
+++ b/wasm/InputGlobal.h
@@ -30,11 +30,11 @@
 
   const WasmGlobalType &getType() const { return Global.Type; }
 
-  uint32_t getOutputIndex() const { return OutputIndex.getValue(); }
-  bool hasOutputIndex() const { return OutputIndex.hasValue(); }
-  void setOutputIndex(uint32_t Index) {
-    assert(!hasOutputIndex());
-    OutputIndex = Index;
+  uint32_t getGlobalIndex() const { return GlobalIndex.getValue(); }
+  bool hasGlobalIndex() const { return GlobalIndex.hasValue(); }
+  void setGlobalIndex(uint32_t Index) {
+    assert(!hasGlobalIndex());
+    GlobalIndex = Index;
   }
 
   bool Live = false;
@@ -42,7 +42,7 @@
   WasmGlobal Global;
 
 protected:
-  llvm::Optional<uint32_t> OutputIndex;
+  llvm::Optional<uint32_t> GlobalIndex;
 };
 
 } // namespace wasm
diff --git a/wasm/MarkLive.cpp b/wasm/MarkLive.cpp
index 22211c1..9b72697 100644
--- a/wasm/MarkLive.cpp
+++ b/wasm/MarkLive.cpp
@@ -73,8 +73,25 @@
     InputChunk *C = Q.pop_back_val();
 
     for (const WasmRelocation Reloc : C->getRelocations()) {
-      if (Reloc.Type != R_WEBASSEMBLY_TYPE_INDEX_LEB)
-        Enqueue(C->File->getSymbol(Reloc.Index));
+      if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB)
+        continue;
+      Symbol *Sym = C->File->getSymbol(Reloc.Index);
+
+      // If the function has been assigned the special index zero in the table,
+      // the relocation doesn't pull in the function body, since the function
+      // won't actually go in the table (the runtime will trap attempts to call
+      // that index, since we don't use it).  A function with a table index of
+      // zero is only reachable via "call", not via "call_indirect".  The stub
+      // functions used for weak-undefined symbols have this behaviour (compare
+      // equal to null pointer, only reachable via direct call).
+      if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB ||
+          Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32) {
+        FunctionSymbol *FuncSym = cast<FunctionSymbol>(Sym);
+        if (FuncSym->hasTableIndex() && FuncSym->getTableIndex() == 0)
+          continue;
+      }
+
+      Enqueue(Sym);
     }
   }
 
diff --git a/wasm/Options.td b/wasm/Options.td
index 6260d4d..a68e350 100644
--- a/wasm/Options.td
+++ b/wasm/Options.td
@@ -11,6 +11,11 @@
   def _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>;
 }
 
+multiclass B<string name, string help1, string help2> {
+  def NAME: Flag<["--", "-"], name>, HelpText<help1>;
+  def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText<help2>;
+}
+
 // The follow flags are shared with the ELF linker
 def color_diagnostics: F<"color-diagnostics">,
   HelpText<"Use colors in diagnostics">;
@@ -18,6 +23,10 @@
 def color_diagnostics_eq: J<"color-diagnostics=">,
   HelpText<"Use colors in diagnostics">;
 
+defm demangle: B<"demangle",
+    "Demangle symbol names",
+    "Do not demangle symbol names">;
+
 def entry: S<"entry">, MetaVarName<"<entry>">,
   HelpText<"Name of entry point symbol">;
 
@@ -27,8 +36,9 @@
 def fatal_warnings: F<"fatal-warnings">,
   HelpText<"Treat warnings as errors">;
 
-def gc_sections: F<"gc-sections">,
-  HelpText<"Enable garbage collection of unused sections">;
+defm gc_sections: B<"gc-sections",
+    "Enable garbage collection of unused sections",
+    "Disable garbage collection of unused sections">;
 
 def help: F<"help">, HelpText<"Print option help">;
 
@@ -48,17 +58,12 @@
 
 def no_fatal_warnings: F<"no-fatal-warnings">;
 
-def no_gc_sections: F<"no-gc-sections">,
-  HelpText<"Disable garbage collection of unused sections">;
-
-def no_print_gc_sections: F<"no-print-gc-sections">,
-  HelpText<"Do not list removed unused sections">;
-
 def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
   HelpText<"Path to file to write output">;
 
-def print_gc_sections: F<"print-gc-sections">,
-  HelpText<"List removed unused sections">;
+defm print_gc_sections: B<"print-gc-sections",
+    "List removed unused sections",
+    "Do not list removed unused sections">;
 
 def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">;
 
@@ -91,27 +96,31 @@
 def allow_undefined_file_s: Separate<["-"], "allow-undefined-file">,
   Alias<allow_undefined_file>;
 
-def check_signatures: F<"check-signatures">,
-  HelpText<"Check function signatures">;
+defm check_signatures: B<"check-signatures",
+    "Check function signatures",
+    "Don't check function signatures">;
 
 defm export: Eq<"export">,
   HelpText<"Force a symbol to be exported">;
 
+def export_table: F<"export-table">,
+  HelpText<"Export function table to the environment">;
+
 def global_base: J<"global-base=">,
   HelpText<"Where to start to place global data">;
 
 def import_memory: F<"import-memory">,
   HelpText<"Import memory from the environment">;
 
+def import_table: F<"import-table">,
+  HelpText<"Import function table from the environment">;
+
 def initial_memory: J<"initial-memory=">,
   HelpText<"Initial size of the linear memory">;
 
 def max_memory: J<"max-memory=">,
   HelpText<"Maximum size of the linear memory">;
 
-def no_check_signatures: F<"no-check-signatures">,
-  HelpText<"Don't check function signatures">;
-
 def no_entry: F<"no-entry">,
   HelpText<"Do not output any entry point">;
 
diff --git a/wasm/OutputSections.cpp b/wasm/OutputSections.cpp
index 915f0aa..9683a2d 100644
--- a/wasm/OutputSections.cpp
+++ b/wasm/OutputSections.cpp
@@ -108,9 +108,8 @@
   memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
 
   // Write code section bodies
-  parallelForEach(Functions, [&](const InputChunk *Chunk) {
-    Chunk->writeTo(Buf);
-  });
+  parallelForEach(Functions,
+                  [&](const InputChunk *Chunk) { Chunk->writeTo(Buf); });
 }
 
 uint32_t CodeSection::numRelocations() const {
diff --git a/wasm/SymbolTable.cpp b/wasm/SymbolTable.cpp
index 6375358..153b507 100644
--- a/wasm/SymbolTable.cpp
+++ b/wasm/SymbolTable.cpp
@@ -119,11 +119,13 @@
 }
 
 DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
-                                                   const WasmSignature *Type,
-                                                   uint32_t Flags) {
+                                                   uint32_t Flags,
+                                                   InputFunction *Function) {
   DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
   assert(!find(Name));
-  return replaceSymbol<DefinedFunction>(insert(Name).first, Name, Flags, Type);
+  SyntheticFunctions.emplace_back(Function);
+  return replaceSymbol<DefinedFunction>(insert(Name).first, Name, Flags,
+                                        nullptr, Function);
 }
 
 DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
@@ -137,6 +139,7 @@
                                                InputGlobal *Global) {
   DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global << "\n");
   assert(!find(Name));
+  SyntheticGlobals.emplace_back(Global);
   return replaceSymbol<DefinedGlobal>(insert(Name).first, Name, Flags, nullptr,
                                       Global);
 }
@@ -301,6 +304,6 @@
   }
 }
 
-bool SymbolTable::addComdat(StringRef Name, const ObjFile *File) {
-  return Comdats.insert({Name, File}).first->second == File;
+bool SymbolTable::addComdat(StringRef Name) {
+  return Comdats.insert(CachedHashStringRef(Name)).second;
 }
diff --git a/wasm/SymbolTable.h b/wasm/SymbolTable.h
index 466ed10..6fb5c15 100644
--- a/wasm/SymbolTable.h
+++ b/wasm/SymbolTable.h
@@ -13,11 +13,11 @@
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "llvm/ADT/CachedHashString.h"
-#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/Support/raw_ostream.h"
 
-using llvm::wasm::WasmSignature;
 using llvm::wasm::WasmGlobalType;
+using llvm::wasm::WasmSignature;
 
 namespace lld {
 namespace wasm {
@@ -41,6 +41,8 @@
   void addFile(InputFile *File);
 
   std::vector<ObjFile *> ObjectFiles;
+  std::vector<InputFunction *> SyntheticFunctions;
+  std::vector<InputGlobal *> SyntheticGlobals;
 
   void reportRemainingUndefines();
 
@@ -63,14 +65,13 @@
 
   void addLazy(ArchiveFile *F, const Archive::Symbol *Sym);
 
-  bool addComdat(StringRef Name, const ObjFile *File);
+  bool addComdat(StringRef Name);
 
   DefinedData *addSyntheticDataSymbol(StringRef Name, uint32_t Flags);
   DefinedGlobal *addSyntheticGlobal(StringRef Name, uint32_t Flags,
                                     InputGlobal *Global);
-  DefinedFunction *addSyntheticFunction(StringRef Name,
-                                        const WasmSignature *Type,
-                                        uint32_t Flags);
+  DefinedFunction *addSyntheticFunction(StringRef Name, uint32_t Flags,
+                                        InputFunction *Function);
 
 private:
   std::pair<Symbol *, bool> insert(StringRef Name);
@@ -78,7 +79,7 @@
   llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap;
   std::vector<Symbol *> SymVector;
 
-  llvm::DenseMap<StringRef, const ObjFile *> Comdats;
+  llvm::DenseSet<llvm::CachedHashStringRef> Comdats;
 };
 
 extern SymbolTable *Symtab;
diff --git a/wasm/Symbols.cpp b/wasm/Symbols.cpp
index 742c887..bcebcdc 100644
--- a/wasm/Symbols.cpp
+++ b/wasm/Symbols.cpp
@@ -39,28 +39,6 @@
   llvm_unreachable("invalid symbol kind");
 }
 
-bool Symbol::hasOutputIndex() const {
-  if (auto *F = dyn_cast<DefinedFunction>(this))
-    if (F->Function)
-      return F->Function->hasOutputIndex();
-  if (auto *G = dyn_cast<DefinedGlobal>(this))
-    if (G->Global)
-      return G->Global->hasOutputIndex();
-  return OutputIndex != INVALID_INDEX;
-}
-
-uint32_t Symbol::getOutputIndex() const {
-  assert(!isa<DataSymbol>(this));
-  if (auto *F = dyn_cast<DefinedFunction>(this))
-    if (F->Function)
-      return F->Function->getOutputIndex();
-  if (auto *G = dyn_cast<DefinedGlobal>(this))
-    if (G->Global)
-      return G->Global->getOutputIndex();
-  assert(OutputIndex != INVALID_INDEX);
-  return OutputIndex;
-}
-
 InputChunk *Symbol::getChunk() const {
   if (auto *F = dyn_cast<DefinedFunction>(this))
     return F->Function;
@@ -89,13 +67,6 @@
   OutputSymbolIndex = Index;
 }
 
-void Symbol::setOutputIndex(uint32_t Index) {
-  DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n");
-  assert(!isa<DataSymbol>(this));
-  assert(OutputIndex == INVALID_INDEX);
-  OutputIndex = Index;
-}
-
 bool Symbol::isWeak() const {
   return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
 }
@@ -117,6 +88,25 @@
     Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
 }
 
+uint32_t FunctionSymbol::getFunctionIndex() const {
+  if (auto *F = dyn_cast<DefinedFunction>(this))
+    return F->Function->getFunctionIndex();
+  assert(FunctionIndex != INVALID_INDEX);
+  return FunctionIndex;
+}
+
+void FunctionSymbol::setFunctionIndex(uint32_t Index) {
+  DEBUG(dbgs() << "setFunctionIndex " << Name << " -> " << Index << "\n");
+  assert(FunctionIndex == INVALID_INDEX);
+  FunctionIndex = Index;
+}
+
+bool FunctionSymbol::hasFunctionIndex() const {
+  if (auto *F = dyn_cast<DefinedFunction>(this))
+    return F->Function->hasFunctionIndex();
+  return FunctionIndex != INVALID_INDEX;
+}
+
 uint32_t FunctionSymbol::getTableIndex() const {
   if (auto *F = dyn_cast<DefinedFunction>(this))
     return F->Function->getTableIndex();
@@ -172,6 +162,25 @@
   return Segment->OutputSeg->Index;
 }
 
+uint32_t GlobalSymbol::getGlobalIndex() const {
+  if (auto *F = dyn_cast<DefinedGlobal>(this))
+    return F->Global->getGlobalIndex();
+  assert(GlobalIndex != INVALID_INDEX);
+  return GlobalIndex;
+}
+
+void GlobalSymbol::setGlobalIndex(uint32_t Index) {
+  DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n");
+  assert(GlobalIndex == INVALID_INDEX);
+  GlobalIndex = Index;
+}
+
+bool GlobalSymbol::hasGlobalIndex() const {
+  if (auto *F = dyn_cast<DefinedGlobal>(this))
+    return F->Global->hasGlobalIndex();
+  return GlobalIndex != INVALID_INDEX;
+}
+
 DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,
                              InputGlobal *Global)
     : GlobalSymbol(Name, DefinedGlobalKind, Flags, File,
@@ -183,7 +192,7 @@
 std::string lld::toString(const wasm::Symbol &Sym) {
   if (Config->Demangle)
     if (Optional<std::string> S = demangleItanium(Sym.getName()))
-      return "`" + *S + "'";
+      return *S;
   return Sym.getName();
 }
 
diff --git a/wasm/Symbols.h b/wasm/Symbols.h
index 90e62e5..92084f7 100644
--- a/wasm/Symbols.h
+++ b/wasm/Symbols.h
@@ -16,9 +16,9 @@
 
 using llvm::object::Archive;
 using llvm::object::WasmSymbol;
-using llvm::wasm::WasmSignature;
 using llvm::wasm::WasmGlobal;
 using llvm::wasm::WasmGlobalType;
+using llvm::wasm::WasmSignature;
 using llvm::wasm::WasmSymbolType;
 
 namespace lld {
@@ -48,8 +48,8 @@
   Kind kind() const { return SymbolKind; }
 
   bool isDefined() const {
-    return SymbolKind == DefinedFunctionKind ||
-           SymbolKind == DefinedDataKind || SymbolKind == DefinedGlobalKind;
+    return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind ||
+           SymbolKind == DefinedGlobalKind;
   }
 
   bool isUndefined() const {
@@ -76,18 +76,8 @@
 
   void setHidden(bool IsHidden);
 
-  uint32_t getOutputIndex() const;
-
-  // Returns true if an output index has been set for this symbol
-  bool hasOutputIndex() const;
-
-  // Set the output index of the symbol, in the Wasm index space of the output
-  // object - that is, for defined symbols only, its position in the list of
-  // Wasm imports+code for functions, imports+globals for globals.
-  void setOutputIndex(uint32_t Index);
-
-  // Get/set the output symbol index, in the Symbol index space.  This is
-  // only used for relocatable output.
+  // Get/set the index in the output symbol table.  This is only used for
+  // relocatable output.
   uint32_t getOutputSymbolIndex() const;
   void setOutputSymbolIndex(uint32_t Index);
 
@@ -101,7 +91,6 @@
   Kind SymbolKind;
   uint32_t Flags;
   InputFile *File;
-  uint32_t OutputIndex = INVALID_INDEX;
   uint32_t OutputSymbolIndex = INVALID_INDEX;
 };
 
@@ -114,13 +103,15 @@
 
   const WasmSignature *getFunctionType() const { return FunctionType; }
 
+  // Get/set the table index
+  void setTableIndex(uint32_t Index);
   uint32_t getTableIndex() const;
-
-  // Returns true if a table index has been set for this symbol
   bool hasTableIndex() const;
 
-  // Set the table index of the symbol
-  void setTableIndex(uint32_t Index);
+  // Get/set the function index
+  uint32_t getFunctionIndex() const;
+  void setFunctionIndex(uint32_t Index);
+  bool hasFunctionIndex() const;
 
 protected:
   FunctionSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
@@ -128,20 +119,16 @@
       : Symbol(Name, K, Flags, F), FunctionType(Type) {}
 
   uint32_t TableIndex = INVALID_INDEX;
+  uint32_t FunctionIndex = INVALID_INDEX;
 
   const WasmSignature *FunctionType;
 };
 
 class DefinedFunction : public FunctionSymbol {
 public:
-  // Primary constructor for file-defined functions.
   DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F,
                   InputFunction *Function);
 
-  // Second constructor used when creating synthetic functions.
-  DefinedFunction(StringRef Name, uint32_t Flags, const WasmSignature *Type)
-      : FunctionSymbol(Name, DefinedFunctionKind, Flags, nullptr, Type) {}
-
   static bool classof(const Symbol *S) {
     return S->kind() == DefinedFunctionKind;
   }
@@ -218,6 +205,11 @@
 
   const WasmGlobalType *getGlobalType() const { return GlobalType; }
 
+  // Get/set the global index
+  uint32_t getGlobalIndex() const;
+  void setGlobalIndex(uint32_t Index);
+  bool hasGlobalIndex() const;
+
 protected:
   GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
                const WasmGlobalType *GlobalType)
@@ -226,6 +218,7 @@
   // Explicit function type, needed for undefined or synthetic functions only.
   // For regular defined globals this information comes from the InputChunk.
   const WasmGlobalType *GlobalType;
+  uint32_t GlobalIndex = INVALID_INDEX;
 };
 
 class DefinedGlobal : public GlobalSymbol {
diff --git a/wasm/Writer.cpp b/wasm/Writer.cpp
index 550372a..a98cfc6 100644
--- a/wasm/Writer.cpp
+++ b/wasm/Writer.cpp
@@ -17,9 +17,11 @@
 #include "WriterUtils.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
+#include "lld/Common/Strings.h"
 #include "lld/Common/Threads.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/Object/WasmTraits.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -37,36 +39,14 @@
 
 static constexpr int kStackAlignment = 16;
 static constexpr int kInitialTableOffset = 1;
+static constexpr const char *kFunctionTableName = "__indirect_function_table";
 
 namespace {
 
-// Traits for using WasmSignature in a DenseMap.
-struct WasmSignatureDenseMapInfo {
-  static WasmSignature getEmptyKey() {
-    WasmSignature Sig;
-    Sig.ReturnType = 1;
-    return Sig;
-  }
-  static WasmSignature getTombstoneKey() {
-    WasmSignature Sig;
-    Sig.ReturnType = 2;
-    return Sig;
-  }
-  static unsigned getHashValue(const WasmSignature &Sig) {
-    unsigned H = hash_value(Sig.ReturnType);
-    for (int32_t Param : Sig.ParamTypes)
-      H = hash_combine(H, Param);
-    return H;
-  }
-  static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) {
-    return LHS == RHS;
-  }
-};
-
 // An init entry to be written to either the synthetic init func or the
 // linking metadata.
 struct WasmInitEntry {
-  const Symbol *Sym;
+  const FunctionSymbol *Sym;
   uint32_t Priority;
 };
 
@@ -92,8 +72,7 @@
   void layoutMemory();
   void createHeader();
   void createSections();
-  SyntheticSection *createSyntheticSection(uint32_t Type,
-                                           StringRef Name = "");
+  SyntheticSection *createSyntheticSection(uint32_t Type, StringRef Name = "");
 
   // Builtin sections
   void createTypeSection();
@@ -117,9 +96,10 @@
 
   uint64_t FileSize = 0;
   uint32_t NumMemoryPages = 0;
+  uint32_t MaxMemoryPages = 0;
 
   std::vector<const WasmSignature *> Types;
-  DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
+  DenseMap<WasmSignature, int32_t> TypeIndices;
   std::vector<const Symbol *> ImportedSymbols;
   unsigned NumImportedFunctions = 0;
   unsigned NumImportedGlobals = 0;
@@ -143,20 +123,12 @@
 
 } // anonymous namespace
 
-static void debugPrint(const char *fmt, ...) {
-  if (!errorHandler().Verbose)
-    return;
-  fprintf(stderr, "lld: ");
-  va_list ap;
-  va_start(ap, fmt);
-  vfprintf(stderr, fmt, ap);
-  va_end(ap);
-}
-
 void Writer::createImportSection() {
   uint32_t NumImports = ImportedSymbols.size();
   if (Config->ImportMemory)
     ++NumImports;
+  if (Config->ImportTable)
+    ++NumImports;
 
   if (NumImports == 0)
     return;
@@ -173,6 +145,21 @@
     Import.Kind = WASM_EXTERNAL_MEMORY;
     Import.Memory.Flags = 0;
     Import.Memory.Initial = NumMemoryPages;
+    if (MaxMemoryPages != 0) {
+      Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
+      Import.Memory.Maximum = MaxMemoryPages;
+    }
+    writeImport(OS, Import);
+  }
+
+  if (Config->ImportTable) {
+    uint32_t TableSize = kInitialTableOffset + IndirectFunctions.size();
+    WasmImport Import;
+    Import.Module = "env";
+    Import.Field = kFunctionTableName;
+    Import.Kind = WASM_EXTERNAL_TABLE;
+    Import.Table.ElemType = WASM_TYPE_ANYFUNC;
+    Import.Table.Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize};
     writeImport(OS, Import);
   }
 
@@ -219,9 +206,13 @@
   SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY);
   raw_ostream &OS = Section->getStream();
 
+  bool HasMax = MaxMemoryPages != 0;
   writeUleb128(OS, 1, "memory count");
-  writeUleb128(OS, 0, "memory limits flags");
+  writeUleb128(OS, HasMax ? static_cast<unsigned>(WASM_LIMITS_FLAG_HAS_MAX) : 0,
+               "memory limits flags");
   writeUleb128(OS, NumMemoryPages, "initial pages");
+  if (HasMax)
+    writeUleb128(OS, MaxMemoryPages, "max pages");
 }
 
 void Writer::createGlobalSection() {
@@ -245,8 +236,11 @@
 }
 
 void Writer::createTableSection() {
-  // Always output a table section, even if there are no indirect calls.
-  // There are two reasons for this:
+  if (Config->ImportTable)
+    return;
+
+  // Always output a table section (or table import), even if there are no
+  // indirect calls.  There are two reasons for this:
   //  1. For executables it is useful to have an empty table slot at 0
   //     which can be filled with a null function call handler.
   //  2. If we don't do this, any program that contains a call_indirect but
@@ -259,16 +253,16 @@
   raw_ostream &OS = Section->getStream();
 
   writeUleb128(OS, 1, "table count");
-  writeU8(OS, WASM_TYPE_ANYFUNC, "table type");
-  writeUleb128(OS, WASM_LIMITS_FLAG_HAS_MAX, "table flags");
-  writeUleb128(OS, TableSize, "table initial size");
-  writeUleb128(OS, TableSize, "table max size");
+  WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize};
+  writeTableType(OS, WasmTable{WASM_TYPE_ANYFUNC, Limits});
 }
 
 void Writer::createExportSection() {
   bool ExportMemory = !Config->Relocatable && !Config->ImportMemory;
+  bool ExportTable = !Config->Relocatable && Config->ExportTable;
 
-  uint32_t NumExports = (ExportMemory ? 1 : 0) + ExportedSymbols.size();
+  uint32_t NumExports =
+      (ExportMemory ? 1 : 0) + (ExportTable ? 1 : 0) + ExportedSymbols.size();
   if (!NumExports)
     return;
 
@@ -279,6 +273,8 @@
 
   if (ExportMemory)
     writeExport(OS, {"memory", WASM_EXTERNAL_MEMORY, 0});
+  if (ExportTable)
+    writeExport(OS, {kFunctionTableName, WASM_EXTERNAL_TABLE, 0});
 
   unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size();
 
@@ -287,10 +283,10 @@
     WasmExport Export;
     DEBUG(dbgs() << "Export: " << Name << "\n");
 
-    if (isa<DefinedFunction>(Sym))
-      Export = {Name, WASM_EXTERNAL_FUNCTION, Sym->getOutputIndex()};
-    else if (isa<DefinedGlobal>(Sym))
-      Export = {Name, WASM_EXTERNAL_GLOBAL, Sym->getOutputIndex()};
+    if (auto *F = dyn_cast<DefinedFunction>(Sym))
+      Export = {Name, WASM_EXTERNAL_FUNCTION, F->getFunctionIndex()};
+    else if (auto *G = dyn_cast<DefinedGlobal>(Sym))
+      Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()};
     else if (isa<DefinedData>(Sym))
       Export = {Name, WASM_EXTERNAL_GLOBAL, FakeGlobalIndex++};
     else
@@ -317,7 +313,7 @@
   uint32_t TableIndex = kInitialTableOffset;
   for (const FunctionSymbol *Sym : IndirectFunctions) {
     assert(Sym->getTableIndex() == TableIndex);
-    writeUleb128(OS, Sym->getOutputIndex(), "function index");
+    writeUleb128(OS, Sym->getFunctionIndex(), "function index");
     ++TableIndex;
   }
 }
@@ -428,14 +424,16 @@
       writeU8(Sub.OS, Kind, "sym kind");
       writeUleb128(Sub.OS, Flags, "sym flags");
 
-      switch (Kind) {
-      case llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION:
-      case llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL:
-        writeUleb128(Sub.OS, Sym->getOutputIndex(), "index");
+      if (auto *F = dyn_cast<FunctionSymbol>(Sym)) {
+        writeUleb128(Sub.OS, F->getFunctionIndex(), "index");
         if (Sym->isDefined())
           writeStr(Sub.OS, Sym->getName(), "sym name");
-        break;
-      case llvm::wasm::WASM_SYMBOL_TYPE_DATA:
+      } else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) {
+        writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
+        if (Sym->isDefined())
+          writeStr(Sub.OS, Sym->getName(), "sym name");
+      } else {
+        assert(isa<DataSymbol>(Sym));
         writeStr(Sub.OS, Sym->getName(), "sym name");
         if (auto *DataSym = dyn_cast<DefinedData>(Sym)) {
           writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index");
@@ -443,7 +441,6 @@
                        "data offset");
           writeUleb128(Sub.OS, DataSym->getSize(), "data size");
         }
-        break;
       }
     }
 
@@ -471,23 +468,26 @@
     Sub.writeTo(OS);
   }
 
-  struct ComdatEntry { unsigned Kind; uint32_t Index; };
-  std::map<StringRef,std::vector<ComdatEntry>> Comdats;
+  struct ComdatEntry {
+    unsigned Kind;
+    uint32_t Index;
+  };
+  std::map<StringRef, std::vector<ComdatEntry>> Comdats;
 
   for (const InputFunction *F : InputFunctions) {
-    StringRef Comdat = F->getComdat();
+    StringRef Comdat = F->getComdatName();
     if (!Comdat.empty())
       Comdats[Comdat].emplace_back(
-          ComdatEntry{WASM_COMDAT_FUNCTION, F->getOutputIndex()});
+          ComdatEntry{WASM_COMDAT_FUNCTION, F->getFunctionIndex()});
   }
   for (uint32_t I = 0; I < Segments.size(); ++I) {
     const auto &InputSegments = Segments[I]->InputSegments;
     if (InputSegments.empty())
       continue;
-    StringRef Comdat = InputSegments[0]->getComdat();
+    StringRef Comdat = InputSegments[0]->getComdatName();
 #ifndef NDEBUG
     for (const InputSegment *IS : InputSegments)
-      assert(IS->getComdat() == Comdat);
+      assert(IS->getComdatName() == Comdat);
 #endif
     if (!Comdat.empty())
       Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I});
@@ -528,15 +528,17 @@
   // and InputFunctions are numbered in order with imported functions coming
   // first.
   for (const Symbol *S : ImportedSymbols) {
-    if (!isa<FunctionSymbol>(S))
-      continue;
-    writeUleb128(Sub.OS, S->getOutputIndex(), "import index");
-    writeStr(Sub.OS, S->getName(), "symbol name");
+    if (auto *F = dyn_cast<FunctionSymbol>(S)) {
+      writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
+      Optional<std::string> Name = demangleItanium(F->getName());
+      writeStr(Sub.OS, Name ? StringRef(*Name) : F->getName(), "symbol name");
+    }
   }
   for (const InputFunction *F : InputFunctions) {
     if (!F->getName().empty()) {
-      writeUleb128(Sub.OS, F->getOutputIndex(), "func index");
-      writeStr(Sub.OS, F->getName(), "symbol name");
+      writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
+      Optional<std::string> Name = demangleItanium(F->getName());
+      writeStr(Sub.OS, Name ? StringRef(*Name) : F->getName(), "symbol name");
     }
   }
 
@@ -562,7 +564,7 @@
 void Writer::layoutMemory() {
   uint32_t MemoryPtr = 0;
   MemoryPtr = Config->GlobalBase;
-  debugPrint("mem: global base = %d\n", Config->GlobalBase);
+  log("mem: global base = " + Twine(Config->GlobalBase));
 
   createOutputSegments();
 
@@ -574,8 +576,8 @@
   for (OutputSegment *Seg : Segments) {
     MemoryPtr = alignTo(MemoryPtr, Seg->Alignment);
     Seg->StartVA = MemoryPtr;
-    debugPrint("mem: %-15s offset=%-8d size=%-8d align=%d\n",
-               Seg->Name.str().c_str(), MemoryPtr, Seg->Size, Seg->Alignment);
+    log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name,
+                MemoryPtr, Seg->Size, Seg->Alignment));
     MemoryPtr += Seg->Size;
   }
 
@@ -583,29 +585,46 @@
   if (WasmSym::DataEnd)
     WasmSym::DataEnd->setVirtualAddress(MemoryPtr);
 
-  debugPrint("mem: static data = %d\n", MemoryPtr - Config->GlobalBase);
+  log("mem: static data = " + Twine(MemoryPtr - Config->GlobalBase));
 
   // Stack comes after static data and bss
   if (!Config->Relocatable) {
     MemoryPtr = alignTo(MemoryPtr, kStackAlignment);
     if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment))
       error("stack size must be " + Twine(kStackAlignment) + "-byte aligned");
-    debugPrint("mem: stack size  = %d\n", Config->ZStackSize);
-    debugPrint("mem: stack base  = %d\n", MemoryPtr);
+    log("mem: stack size  = " + Twine(Config->ZStackSize));
+    log("mem: stack base  = " + Twine(MemoryPtr));
     MemoryPtr += Config->ZStackSize;
     WasmSym::StackPointer->Global->Global.InitExpr.Value.Int32 = MemoryPtr;
-    debugPrint("mem: stack top   = %d\n", MemoryPtr);
+    log("mem: stack top   = " + Twine(MemoryPtr));
 
     // Set `__heap_base` to directly follow the end of the stack.  We don't
     // allocate any heap memory up front, but instead really on the malloc/brk
     // implementation growing the memory at runtime.
     WasmSym::HeapBase->setVirtualAddress(MemoryPtr);
-    debugPrint("mem: heap base   = %d\n", MemoryPtr);
+    log("mem: heap base   = " + Twine(MemoryPtr));
   }
 
+  if (Config->InitialMemory != 0) {
+    if (Config->InitialMemory != alignTo(Config->InitialMemory, WasmPageSize))
+      error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned");
+    if (MemoryPtr > Config->InitialMemory)
+      error("initial memory too small, " + Twine(MemoryPtr) + " bytes needed");
+    else
+      MemoryPtr = Config->InitialMemory;
+  }
   uint32_t MemSize = alignTo(MemoryPtr, WasmPageSize);
   NumMemoryPages = MemSize / WasmPageSize;
-  debugPrint("mem: total pages = %d\n", NumMemoryPages);
+  log("mem: total pages = " + Twine(NumMemoryPages));
+
+  if (Config->MaxMemory != 0) {
+    if (Config->MaxMemory != alignTo(Config->MaxMemory, WasmPageSize))
+      error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned");
+    if (MemoryPtr > Config->MaxMemory)
+      error("maximum memory too small, " + Twine(MemoryPtr) + " bytes needed");
+    MaxMemoryPages = Config->MaxMemory / WasmPageSize;
+    log("mem: max pages   = " + Twine(MaxMemoryPages));
+  }
 }
 
 SyntheticSection *Writer::createSyntheticSection(uint32_t Type,
@@ -654,12 +673,11 @@
       continue;
 
     DEBUG(dbgs() << "import: " << Sym->getName() << "\n");
-    Sym->setOutputIndex(ImportedSymbols.size());
     ImportedSymbols.emplace_back(Sym);
-    if (isa<FunctionSymbol>(Sym))
-      ++NumImportedFunctions;
+    if (auto *F = dyn_cast<FunctionSymbol>(Sym))
+      F->setFunctionIndex(NumImportedFunctions++);
     else
-      ++NumImportedGlobals;
+      cast<GlobalSymbol>(Sym)->setGlobalIndex(NumImportedGlobals++);
   }
 }
 
@@ -693,8 +711,9 @@
     for (Symbol *Sym : File->getSymbols()) {
       if (Sym->getFile() != File)
         continue;
-      if (!Sym->isLive())
-        return;
+      // (Since this is relocatable output, GC is not performed so symbols must
+      // be live.)
+      assert(Sym->isLive());
       Sym->setOutputSymbolIndex(SymbolIndex++);
       SymtabEntries.emplace_back(Sym);
     }
@@ -746,14 +765,20 @@
 
 void Writer::assignIndexes() {
   uint32_t FunctionIndex = NumImportedFunctions + InputFunctions.size();
+  auto AddDefinedFunction = [&](InputFunction *Func) {
+    if (!Func->Live)
+      return;
+    InputFunctions.emplace_back(Func);
+    Func->setFunctionIndex(FunctionIndex++);
+  };
+
+  for (InputFunction *Func : Symtab->SyntheticFunctions)
+    AddDefinedFunction(Func);
+
   for (ObjFile *File : Symtab->ObjectFiles) {
     DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
-    for (InputFunction *Func : File->Functions) {
-      if (!Func->Live)
-        continue;
-      InputFunctions.emplace_back(Func);
-      Func->setOutputIndex(FunctionIndex++);
-    }
+    for (InputFunction *Func : File->Functions)
+      AddDefinedFunction(Func);
   }
 
   uint32_t TableIndex = kInitialTableOffset;
@@ -766,7 +791,7 @@
       if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32 ||
           Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB) {
         FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index);
-        if (Sym->hasTableIndex() || !Sym->hasOutputIndex())
+        if (Sym->hasTableIndex() || !Sym->hasFunctionIndex())
           continue;
         Sym->setTableIndex(TableIndex++);
         IndirectFunctions.emplace_back(Sym);
@@ -797,13 +822,13 @@
   auto AddDefinedGlobal = [&](InputGlobal *Global) {
     if (Global->Live) {
       DEBUG(dbgs() << "AddDefinedGlobal: " << GlobalIndex << "\n");
-      Global->setOutputIndex(GlobalIndex++);
+      Global->setGlobalIndex(GlobalIndex++);
       InputGlobals.push_back(Global);
     }
   };
 
-  if (WasmSym::StackPointer)
-    AddDefinedGlobal(WasmSym::StackPointer->Global);
+  for (InputGlobal *Global : Symtab->SyntheticGlobals)
+    AddDefinedGlobal(Global);
 
   for (ObjFile *File : Symtab->ObjectFiles) {
     DEBUG(dbgs() << "Globals: " << File->getName() << "\n");
@@ -848,9 +873,6 @@
 // Create synthetic "__wasm_call_ctors" function based on ctor functions
 // in input object.
 void Writer::createCtorFunction() {
-  uint32_t FunctionIndex = NumImportedFunctions + InputFunctions.size();
-  WasmSym::CallCtors->setOutputIndex(FunctionIndex);
-
   // First write the body's contents to a string.
   std::string BodyContent;
   {
@@ -858,7 +880,7 @@
     writeUleb128(OS, 0, "num locals");
     for (const WasmInitEntry &F : InitFunctions) {
       writeU8(OS, OPCODE_CALL, "CALL");
-      writeUleb128(OS, F.Sym->getOutputIndex(), "function index");
+      writeUleb128(OS, F.Sym->getFunctionIndex(), "function index");
     }
     writeU8(OS, OPCODE_END, "END");
   }
@@ -871,14 +893,8 @@
     OS << BodyContent;
   }
 
-  const WasmSignature *Sig = WasmSym::CallCtors->getFunctionType();
-  SyntheticFunction *F = make<SyntheticFunction>(
-      *Sig, std::move(FunctionBody), WasmSym::CallCtors->getName());
-
-  F->setOutputIndex(FunctionIndex);
-  F->Live = true;
-  WasmSym::CallCtors->Function = F;
-  InputFunctions.emplace_back(F);
+  ArrayRef<uint8_t> Body = toArrayRef(Saver.save(FunctionBody));
+  cast<SyntheticFunction>(WasmSym::CallCtors->Function)->setBody(Body);
 }
 
 // Populate InitFunctions vector with init functions from all input objects.
diff --git a/wasm/WriterUtils.cpp b/wasm/WriterUtils.cpp
index e2494b5..4c0d09e 100644
--- a/wasm/WriterUtils.cpp
+++ b/wasm/WriterUtils.cpp
@@ -126,6 +126,11 @@
   writeInitExpr(OS, Global.InitExpr);
 }
 
+void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) {
+  writeU8(OS, WASM_TYPE_ANYFUNC, "table type");
+  writeLimits(OS, Type.Limits);
+}
+
 void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {
   writeStr(OS, Import.Module, "import module name");
   writeStr(OS, Import.Field, "import field name");
@@ -140,6 +145,9 @@
   case WASM_EXTERNAL_MEMORY:
     writeLimits(OS, Import.Memory);
     break;
+  case WASM_EXTERNAL_TABLE:
+    writeTableType(OS, Import.Table);
+    break;
   default:
     fatal("unsupported import type: " + Twine(Import.Kind));
   }
@@ -158,6 +166,9 @@
   case WASM_EXTERNAL_MEMORY:
     writeUleb128(OS, Export.Index, "memory index");
     break;
+  case WASM_EXTERNAL_TABLE:
+    writeUleb128(OS, Export.Index, "table index");
+    break;
   default:
     fatal("unsupported export type: " + Twine(Export.Kind));
   }
@@ -174,6 +185,8 @@
     return "F32";
   case ValType::F64:
     return "F64";
+  case ValType::EXCEPT_REF:
+    return "except_ref";
   }
   llvm_unreachable("Invalid wasm::ValType");
 }
@@ -195,5 +208,5 @@
 
 std::string lld::toString(const WasmGlobalType &Sig) {
   return (Sig.Mutable ? "var " : "const ") +
-      toString(static_cast<ValType>(Sig.Type));
+         toString(static_cast<ValType>(Sig.Type));
 }
diff --git a/wasm/WriterUtils.h b/wasm/WriterUtils.h
index 6721ef4..74d727b 100644
--- a/wasm/WriterUtils.h
+++ b/wasm/WriterUtils.h
@@ -17,28 +17,6 @@
 
 using llvm::raw_ostream;
 
-// Needed for WasmSignatureDenseMapInfo
-inline bool operator==(const llvm::wasm::WasmSignature &LHS,
-                       const llvm::wasm::WasmSignature &RHS) {
-  return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes;
-}
-
-inline bool operator!=(const llvm::wasm::WasmSignature &LHS,
-                       const llvm::wasm::WasmSignature &RHS) {
-  return !(LHS == RHS);
-}
-
-// Used for general comparison
-inline bool operator==(const llvm::wasm::WasmGlobalType &LHS,
-                       const llvm::wasm::WasmGlobalType &RHS) {
-  return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable;
-}
-
-inline bool operator!=(const llvm::wasm::WasmGlobalType &LHS,
-                       const llvm::wasm::WasmGlobalType &RHS) {
-  return !(LHS == RHS);
-}
-
 namespace lld {
 namespace wasm {
 
@@ -69,13 +47,15 @@
 
 void writeGlobal(raw_ostream &OS, const llvm::wasm::WasmGlobal &Global);
 
+void writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type);
+
 void writeImport(raw_ostream &OS, const llvm::wasm::WasmImport &Import);
 
 void writeExport(raw_ostream &OS, const llvm::wasm::WasmExport &Export);
 
 } // namespace wasm
 
-std::string toString(const llvm::wasm::ValType Type);
+std::string toString(llvm::wasm::ValType Type);
 std::string toString(const llvm::wasm::WasmSignature &Sig);
 std::string toString(const llvm::wasm::WasmGlobalType &Sig);