Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 May 2017 16:26:20 +0000 (UTC)
From:      Dimitry Andric <dim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r319148 - in vendor/lld/dist: COFF ELF test/COFF test/COFF/Inputs test/ELF test/ELF/Inputs test/ELF/linkerscript test/ELF/lto test/ELF/lto/Inputs
Message-ID:  <201705291626.v4TGQKom083418@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dim
Date: Mon May 29 16:26:20 2017
New Revision: 319148
URL: https://svnweb.freebsd.org/changeset/base/319148

Log:
  Vendor import of lld trunk r304149:
  https://llvm.org/svn/llvm-project/lld/trunk@304149

Added:
  vendor/lld/dist/test/COFF/Inputs/delayimports-error.yaml
  vendor/lld/dist/test/COFF/Inputs/oldname.yaml
  vendor/lld/dist/test/COFF/delayimports-error.test
  vendor/lld/dist/test/COFF/dllimport-gc.test
  vendor/lld/dist/test/ELF/Inputs/rodynamic.s   (contents, props changed)
  vendor/lld/dist/test/ELF/gdb-index-dup-types.s   (contents, props changed)
  vendor/lld/dist/test/ELF/linkerscript/arm-lscript.s   (contents, props changed)
  vendor/lld/dist/test/ELF/lto/Inputs/relocation-model-pic.ll
  vendor/lld/dist/test/ELF/lto/relocation-model.ll
  vendor/lld/dist/test/ELF/relocatable-comdat.s   (contents, props changed)
  vendor/lld/dist/test/ELF/rodynamic.s   (contents, props changed)
Modified:
  vendor/lld/dist/COFF/ICF.cpp
  vendor/lld/dist/COFF/InputFiles.cpp
  vendor/lld/dist/COFF/InputFiles.h
  vendor/lld/dist/COFF/MarkLive.cpp
  vendor/lld/dist/COFF/PDB.cpp
  vendor/lld/dist/COFF/Symbols.cpp
  vendor/lld/dist/COFF/Symbols.h
  vendor/lld/dist/COFF/Writer.cpp
  vendor/lld/dist/ELF/Config.h
  vendor/lld/dist/ELF/Driver.cpp
  vendor/lld/dist/ELF/ICF.cpp
  vendor/lld/dist/ELF/InputFiles.cpp
  vendor/lld/dist/ELF/InputSection.cpp
  vendor/lld/dist/ELF/InputSection.h
  vendor/lld/dist/ELF/LTO.cpp
  vendor/lld/dist/ELF/LinkerScript.cpp
  vendor/lld/dist/ELF/LinkerScript.h
  vendor/lld/dist/ELF/MapFile.cpp
  vendor/lld/dist/ELF/Options.td
  vendor/lld/dist/ELF/OutputSections.cpp
  vendor/lld/dist/ELF/OutputSections.h
  vendor/lld/dist/ELF/SyntheticSections.cpp
  vendor/lld/dist/ELF/SyntheticSections.h
  vendor/lld/dist/ELF/Writer.cpp
  vendor/lld/dist/ELF/Writer.h
  vendor/lld/dist/test/COFF/Inputs/import.yaml
  vendor/lld/dist/test/ELF/amdgpu-globals.s
  vendor/lld/dist/test/ELF/build-id.s
  vendor/lld/dist/test/ELF/gc-sections.s
  vendor/lld/dist/test/ELF/i386-tls-ie-shared.s
  vendor/lld/dist/test/ELF/linkerscript/sections-constraint.s
  vendor/lld/dist/test/ELF/relocation-size-shared.s
  vendor/lld/dist/test/ELF/relocation-size.s
  vendor/lld/dist/test/ELF/reproduce.s
  vendor/lld/dist/test/ELF/section-layout.s
  vendor/lld/dist/test/ELF/tls-i686.s

Modified: vendor/lld/dist/COFF/ICF.cpp
==============================================================================
--- vendor/lld/dist/COFF/ICF.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/ICF.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -56,7 +56,6 @@ private:
 
   std::vector<SectionChunk *> Chunks;
   int Cnt = 0;
-  std::atomic<uint32_t> NextId = {1};
   std::atomic<bool> Repeat = {false};
 };
 
@@ -98,10 +97,10 @@ void ICF::segregate(size_t Begin, size_t
         });
     size_t Mid = Bound - Chunks.begin();
 
-    // Split [Begin, End) into [Begin, Mid) and [Mid, End).
-    uint32_t Id = NextId++;
+    // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an
+    // equivalence class ID because every group ends with a unique index.
     for (size_t I = Begin; I < Mid; ++I)
-      Chunks[I]->Class[(Cnt + 1) % 2] = Id;
+      Chunks[I]->Class[(Cnt + 1) % 2] = Mid;
 
     // If we created a group, we need to iterate the main loop again.
     if (Mid != End)
@@ -186,6 +185,7 @@ void ICF::forEachClass(std::function<voi
   // call Fn sequentially.
   if (Chunks.size() < 1024) {
     forEachClassRange(0, Chunks.size(), Fn);
+    ++Cnt;
     return;
   }
 
@@ -193,9 +193,10 @@ void ICF::forEachClass(std::function<voi
   size_t NumShards = 256;
   size_t Step = Chunks.size() / NumShards;
   for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
-    forEachClassRange(I * Step, (I + 1) * Step, Fn);
+    size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
+    forEachClassRange(I * Step, End, Fn);
   });
-  forEachClassRange(Step * NumShards, Chunks.size(), Fn);
+  ++Cnt;
 }
 
 // Merge identical COMDAT sections.
@@ -203,22 +204,20 @@ void ICF::forEachClass(std::function<voi
 // contents and relocations are all the same.
 void ICF::run(const std::vector<Chunk *> &Vec) {
   // Collect only mergeable sections and group by hash value.
+  uint32_t NextId = 1;
   for (Chunk *C : Vec) {
-    auto *SC = dyn_cast<SectionChunk>(C);
-    if (!SC)
-      continue;
-
-    if (isEligible(SC)) {
-      // Set MSB to 1 to avoid collisions with non-hash classs.
-      SC->Class[0] = getHash(SC) | (1 << 31);
-      Chunks.push_back(SC);
-    } else {
-      SC->Class[0] = NextId++;
+    if (auto *SC = dyn_cast<SectionChunk>(C)) {
+      if (isEligible(SC))
+        Chunks.push_back(SC);
+      else
+        SC->Class[0] = NextId++;
     }
   }
 
-  if (Chunks.empty())
-    return;
+  // Initially, we use hash values to partition sections.
+  for (SectionChunk *SC : Chunks)
+    // Set MSB to 1 to avoid collisions with non-hash classs.
+    SC->Class[0] = getHash(SC) | (1 << 31);
 
   // From now on, sections in Chunks are ordered so that sections in
   // the same group are consecutive in the vector.
@@ -229,14 +228,12 @@ void ICF::run(const std::vector<Chunk *>
 
   // Compare static contents and assign unique IDs for each static content.
   forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); });
-  ++Cnt;
 
   // Split groups by comparing relocations until convergence is obtained.
   do {
     Repeat = false;
     forEachClass(
         [&](size_t Begin, size_t End) { segregate(Begin, End, false); });
-    ++Cnt;
   } while (Repeat);
 
   log("ICF needed " + Twine(Cnt) + " iterations");

Modified: vendor/lld/dist/COFF/InputFiles.cpp
==============================================================================
--- vendor/lld/dist/COFF/InputFiles.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/InputFiles.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -48,13 +48,11 @@ namespace coff {
 /// alias to Target.
 static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F,
                                  SymbolBody *Source, SymbolBody *Target) {
-  auto *U = dyn_cast<Undefined>(Source);
-  if (!U)
-    return;
-  else if (!U->WeakAlias)
+  if (auto *U = dyn_cast<Undefined>(Source)) {
+    if (U->WeakAlias && U->WeakAlias != Target)
+      Symtab->reportDuplicate(Source->symbol(), F);
     U->WeakAlias = Target;
-  else if (U->WeakAlias != Target)
-    Symtab->reportDuplicate(Source->symbol(), F);
+  }
 }
 
 ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
@@ -153,8 +151,10 @@ void ObjectFile::initializeSymbols() {
   uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
   SymbolBodies.reserve(NumSymbols);
   SparseSymbolBodies.resize(NumSymbols);
+
   SmallVector<std::pair<SymbolBody *, uint32_t>, 8> WeakAliases;
   int32_t LastSectionNumber = 0;
+
   for (uint32_t I = 0; I < NumSymbols; ++I) {
     // Get a COFFSymbolRef object.
     ErrorOr<COFFSymbolRef> SymOrErr = COFFObj->getSymbol(I);
@@ -185,9 +185,12 @@ void ObjectFile::initializeSymbols() {
     I += Sym.getNumberOfAuxSymbols();
     LastSectionNumber = Sym.getSectionNumber();
   }
-  for (auto WeakAlias : WeakAliases)
-    checkAndSetWeakAlias(Symtab, this, WeakAlias.first,
-                         SparseSymbolBodies[WeakAlias.second]);
+
+  for (auto &KV : WeakAliases) {
+    SymbolBody *Sym = KV.first;
+    uint32_t Idx = KV.second;
+    checkAndSetWeakAlias(Symtab, this, Sym, SparseSymbolBodies[Idx]);
+  }
 }
 
 SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) {

Modified: vendor/lld/dist/COFF/InputFiles.h
==============================================================================
--- vendor/lld/dist/COFF/InputFiles.h	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/InputFiles.h	Mon May 29 16:26:20 2017	(r319148)
@@ -10,6 +10,7 @@
 #ifndef LLD_COFF_INPUT_FILES_H
 #define LLD_COFF_INPUT_FILES_H
 
+#include "Config.h"
 #include "lld/Core/LLVM.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseSet.h"
@@ -161,7 +162,9 @@ private:
 // for details about the format.
 class ImportFile : public InputFile {
 public:
-  explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M) {}
+  explicit ImportFile(MemoryBufferRef M)
+      : InputFile(ImportKind, M), Live(!Config->DoGC) {}
+
   static bool classof(const InputFile *F) { return F->kind() == ImportKind; }
 
   DefinedImportData *ImpSym = nullptr;
@@ -176,6 +179,14 @@ public:
   StringRef ExternalName;
   const coff_import_header *Hdr;
   Chunk *Location = nullptr;
+
+  // We want to eliminate dllimported symbols if no one actually refers them.
+  // This "Live" bit is used to keep track of which import library members
+  // are actually in use.
+  //
+  // If the Live bit is turned off by MarkLive, Writer will ignore dllimported
+  // symbols provided by this import library member.
+  bool Live;
 };
 
 // Used for LTO.

Modified: vendor/lld/dist/COFF/MarkLive.cpp
==============================================================================
--- vendor/lld/dist/COFF/MarkLive.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/MarkLive.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -37,19 +37,26 @@ void markLive(const std::vector<Chunk *>
     Worklist.push_back(C);
   };
 
+  auto AddSym = [&](SymbolBody *B) {
+    if (auto *Sym = dyn_cast<DefinedRegular>(B))
+      Enqueue(Sym->getChunk());
+    else if (auto *Sym = dyn_cast<DefinedImportData>(B))
+      Sym->File->Live = true;
+    else if (auto *Sym = dyn_cast<DefinedImportThunk>(B))
+      Sym->WrappedSym->File->Live = true;
+  };
+
   // Add GC root chunks.
   for (SymbolBody *B : Config->GCRoot)
-    if (auto *D = dyn_cast<DefinedRegular>(B))
-      Enqueue(D->getChunk());
+    AddSym(B);
 
   while (!Worklist.empty()) {
     SectionChunk *SC = Worklist.pop_back_val();
     assert(SC->isLive() && "We mark as live when pushing onto the worklist!");
 
     // Mark all symbols listed in the relocation table for this section.
-    for (SymbolBody *S : SC->symbols())
-      if (auto *D = dyn_cast<DefinedRegular>(S))
-        Enqueue(D->getChunk());
+    for (SymbolBody *B : SC->symbols())
+      AddSym(B);
 
     // Mark associative sections if any.
     for (SectionChunk *C : SC->children())

Modified: vendor/lld/dist/COFF/PDB.cpp
==============================================================================
--- vendor/lld/dist/COFF/PDB.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/PDB.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -99,6 +99,12 @@ static void addTypeInfo(pdb::TpiStreamBu
 static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
                         codeview::TypeTableBuilder &TypeTable,
                         codeview::TypeTableBuilder &IDTable) {
+  // Follow type servers.  If the same type server is encountered more than
+  // once for this instance of `PDBTypeServerHandler` (for example if many
+  // object files reference the same TypeServer), the types from the
+  // TypeServer will only be visited once.
+  pdb::PDBTypeServerHandler Handler;
+
   // Visit all .debug$T sections to add them to Builder.
   for (ObjectFile *File : Symtab->ObjectFiles) {
     ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
@@ -109,16 +115,11 @@ static void mergeDebugT(SymbolTable *Sym
     codeview::CVTypeArray Types;
     BinaryStreamReader Reader(Stream);
     SmallVector<TypeIndex, 128> SourceToDest;
-    // Follow type servers.  If the same type server is encountered more than
-    // once for this instance of `PDBTypeServerHandler` (for example if many
-    // object files reference the same TypeServer), the types from the
-    // TypeServer will only be visited once.
-    pdb::PDBTypeServerHandler Handler;
     Handler.addSearchPath(llvm::sys::path::parent_path(File->getName()));
     if (auto EC = Reader.readArray(Types, Reader.getLength()))
       fatal(EC, "Reader::readArray failed");
-    if (auto Err = codeview::mergeTypeStreams(IDTable, TypeTable, SourceToDest,
-                                              &Handler, Types))
+    if (auto Err = codeview::mergeTypeAndIdRecords(
+            IDTable, TypeTable, SourceToDest, &Handler, Types))
       fatal(Err, "codeview::mergeTypeStreams failed");
   }
 

Modified: vendor/lld/dist/COFF/Symbols.cpp
==============================================================================
--- vendor/lld/dist/COFF/Symbols.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/Symbols.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -61,16 +61,19 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol
   return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
 }
 
+static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {
+  if (Machine == AMD64)
+    return make<ImportThunkChunkX64>(S);
+  if (Machine == I386)
+    return make<ImportThunkChunkX86>(S);
+  assert(Machine == ARMNT);
+  return make<ImportThunkChunkARM>(S);
+}
+
 DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,
                                        uint16_t Machine)
-    : Defined(DefinedImportThunkKind, Name) {
-  switch (Machine) {
-  case AMD64: Data = make<ImportThunkChunkX64>(S); return;
-  case I386:  Data = make<ImportThunkChunkX86>(S); return;
-  case ARMNT: Data = make<ImportThunkChunkARM>(S); return;
-  default:    llvm_unreachable("unknown machine type");
-  }
-}
+    : Defined(DefinedImportThunkKind, Name), WrappedSym(S),
+      Data(makeImportThunk(S, Machine)) {}
 
 Defined *Undefined::getWeakAlias() {
   // A weak alias may be a weak alias to another symbol, so check recursively.

Modified: vendor/lld/dist/COFF/Symbols.h
==============================================================================
--- vendor/lld/dist/COFF/Symbols.h	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/Symbols.h	Mon May 29 16:26:20 2017	(r319148)
@@ -300,7 +300,6 @@ public:
   void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
   uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
 
-private:
   ImportFile *File;
 };
 
@@ -320,6 +319,8 @@ public:
   uint64_t getRVA() { return Data->getRVA(); }
   Chunk *getChunk() { return Data; }
 
+  DefinedImportData *WrappedSym;
+
 private:
   Chunk *Data;
 };

Modified: vendor/lld/dist/COFF/Writer.cpp
==============================================================================
--- vendor/lld/dist/COFF/Writer.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/COFF/Writer.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -365,6 +365,9 @@ void Writer::createImportTables() {
   // the same order as in the command line. (That affects DLL
   // initialization order, and this ordering is MSVC-compatible.)
   for (ImportFile *File : Symtab->ImportFiles) {
+    if (!File->Live)
+      continue;
+
     std::string DLL = StringRef(File->DLLName).lower();
     if (Config->DLLOrder.count(DLL) == 0)
       Config->DLLOrder[DLL] = Config->DLLOrder.size();
@@ -372,19 +375,28 @@ void Writer::createImportTables() {
 
   OutputSection *Text = createSection(".text");
   for (ImportFile *File : Symtab->ImportFiles) {
+    if (!File->Live)
+      continue;
+
     if (DefinedImportThunk *Thunk = File->ThunkSym)
       Text->addChunk(Thunk->getChunk());
+
     if (Config->DelayLoads.count(StringRef(File->DLLName).lower())) {
+      if (!File->ThunkSym)
+        fatal("cannot delay-load " + toString(File) +
+              " due to import of data: " + toString(*File->ImpSym));
       DelayIdata.add(File->ImpSym);
     } else {
       Idata.add(File->ImpSym);
     }
   }
+
   if (!Idata.empty()) {
     OutputSection *Sec = createSection(".idata");
     for (Chunk *C : Idata.getChunks())
       Sec->addChunk(C);
   }
+
   if (!DelayIdata.empty()) {
     Defined *Helper = cast<Defined>(Config->DelayLoadHelper);
     DelayIdata.create(Helper);
@@ -437,6 +449,14 @@ Optional<coff_symbol16> Writer::createSy
     if (!D->getChunk()->isLive())
       return None;
 
+  if (auto *Sym = dyn_cast<DefinedImportData>(Def))
+    if (!Sym->File->Live)
+      return None;
+
+  if (auto *Sym = dyn_cast<DefinedImportThunk>(Def))
+    if (!Sym->WrappedSym->File->Live)
+      return None;
+
   coff_symbol16 Sym;
   StringRef Name = Def->getName();
   if (Name.size() > COFF::NameSize) {
@@ -491,14 +511,17 @@ void Writer::createSymbolAndStringTable(
     Sec->setStringTableOff(addEntryToStringTable(Name));
   }
 
-  for (lld::coff::ObjectFile *File : Symtab->ObjectFiles)
-    for (SymbolBody *B : File->getSymbols())
-      if (auto *D = dyn_cast<Defined>(B))
-        if (!D->WrittenToSymtab) {
-          D->WrittenToSymtab = true;
-          if (Optional<coff_symbol16> Sym = createSymbol(D))
-            OutputSymtab.push_back(*Sym);
-        }
+  for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) {
+    for (SymbolBody *B : File->getSymbols()) {
+      auto *D = dyn_cast<Defined>(B);
+      if (!D || D->WrittenToSymtab)
+        continue;
+      D->WrittenToSymtab = true;
+
+      if (Optional<coff_symbol16> Sym = createSymbol(D))
+        OutputSymtab.push_back(*Sym);
+    }
+  }
 
   OutputSection *LastSection = OutputSections.back();
   // We position the symbol table to be adjacent to the end of the last section.
@@ -782,19 +805,15 @@ void Writer::writeBuildId() {
   if (BuildId == nullptr)
     return;
 
-  MD5 Hash;
-  MD5::MD5Result Res;
-
-  Hash.update(ArrayRef<uint8_t>{Buffer->getBufferStart(),
-                                Buffer->getBufferEnd()});
-  Hash.final(Res);
-
   assert(BuildId->DI->Signature.CVSignature == OMF::Signature::PDB70 &&
          "only PDB 7.0 is supported");
-  assert(sizeof(Res) == sizeof(BuildId->DI->PDB70.Signature) &&
+  assert(sizeof(BuildId->DI->PDB70.Signature) == 16 &&
          "signature size mismatch");
-  memcpy(BuildId->DI->PDB70.Signature, Res.Bytes.data(),
-         sizeof(codeview::PDB70DebugInfo::Signature));
+
+  // Compute an MD5 hash.
+  ArrayRef<uint8_t> Buf(Buffer->getBufferStart(), Buffer->getBufferEnd());
+  memcpy(BuildId->DI->PDB70.Signature, MD5::hash(Buf).data(), 16);
+
   // TODO(compnerd) track the Age
   BuildId->DI->PDB70.Age = 1;
 }

Modified: vendor/lld/dist/ELF/Config.h
==============================================================================
--- vendor/lld/dist/ELF/Config.h	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/Config.h	Mon May 29 16:26:20 2017	(r319148)
@@ -145,6 +145,7 @@ struct Configuration {
   bool ZNow;
   bool ZOrigin;
   bool ZRelro;
+  bool ZRodynamic;
   bool ZText;
   bool ExitEarly;
   bool ZWxneeded;

Modified: vendor/lld/dist/ELF/Driver.cpp
==============================================================================
--- vendor/lld/dist/ELF/Driver.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/Driver.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -572,10 +572,14 @@ static std::pair<bool, bool> getHashStyl
 // -build-id=sha1 are actually tree hashes for performance reasons.
 static std::pair<BuildIdKind, std::vector<uint8_t>>
 getBuildId(opt::InputArgList &Args) {
-  if (Args.hasArg(OPT_build_id))
+  auto *Arg = Args.getLastArg(OPT_build_id, OPT_build_id_eq);
+  if (!Arg)
+    return {BuildIdKind::None, {}};
+
+  if (Arg->getOption().getID() == OPT_build_id)
     return {BuildIdKind::Fast, {}};
 
-  StringRef S = getString(Args, OPT_build_id_eq, "none");
+  StringRef S = Arg->getValue();
   if (S == "md5")
     return {BuildIdKind::Md5, {}};
   if (S == "sha1" || S == "tree")
@@ -688,6 +692,7 @@ void LinkerDriver::readConfigs(opt::Inpu
   Config->ZNow = hasZOption(Args, "now");
   Config->ZOrigin = hasZOption(Args, "origin");
   Config->ZRelro = !hasZOption(Args, "norelro");
+  Config->ZRodynamic = hasZOption(Args, "rodynamic");
   Config->ZStackSize = getZOptionValue(Args, "stack-size", 0);
   Config->ZText = !hasZOption(Args, "notext");
   Config->ZWxneeded = hasZOption(Args, "wxneeded");

Modified: vendor/lld/dist/ELF/ICF.cpp
==============================================================================
--- vendor/lld/dist/ELF/ICF.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/ICF.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -326,9 +326,9 @@ void ICF<ELFT>::forEachClass(std::functi
   size_t NumShards = 256;
   size_t Step = Sections.size() / NumShards;
   parallelForEachN(0, NumShards, [&](size_t I) {
-    forEachClassRange(I * Step, (I + 1) * Step, Fn);
+    size_t End = (I == NumShards - 1) ? Sections.size() : (I + 1) * Step;
+    forEachClassRange(I * Step, End, Fn);
   });
-  forEachClassRange(Step * NumShards, Sections.size(), Fn);
   ++Cnt;
 }
 

Modified: vendor/lld/dist/ELF/InputFiles.cpp
==============================================================================
--- vendor/lld/dist/ELF/InputFiles.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/InputFiles.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -281,18 +281,20 @@ bool elf::ObjectFile<ELFT>::shouldMerge(
 template <class ELFT>
 void elf::ObjectFile<ELFT>::initializeSections(
     DenseSet<CachedHashStringRef> &ComdatGroups) {
+  const ELFFile<ELFT> &Obj = this->getObj();
+
   ArrayRef<Elf_Shdr> ObjSections =
       check(this->getObj().sections(), toString(this));
-  const ELFFile<ELFT> &Obj = this->getObj();
   uint64_t Size = ObjSections.size();
   this->Sections.resize(Size);
-  unsigned I = -1;
+
   StringRef SectionStringTable =
       check(Obj.getSectionStringTable(ObjSections), toString(this));
-  for (const Elf_Shdr &Sec : ObjSections) {
-    ++I;
+
+  for (size_t I = 0, E = ObjSections.size(); I < E; I++) {
     if (this->Sections[I] == &InputSection::Discarded)
       continue;
+    const Elf_Shdr &Sec = ObjSections[I];
 
     // SHF_EXCLUDE'ed sections are discarded by the linker. However,
     // if -r is given, we'll let the final link discard such sections.
@@ -303,13 +305,22 @@ void elf::ObjectFile<ELFT>::initializeSe
     }
 
     switch (Sec.sh_type) {
-    case SHT_GROUP:
-      this->Sections[I] = &InputSection::Discarded;
-      if (ComdatGroups
-              .insert(
-                  CachedHashStringRef(getShtGroupSignature(ObjSections, Sec)))
-              .second)
+    case SHT_GROUP: {
+      // We discard comdat sections usually. When -r we should not do that. We
+      // still do deduplication in this case to simplify implementation, because
+      // otherwise merging group sections together would requre additional
+      // regeneration of its contents.
+      bool New = ComdatGroups
+                     .insert(CachedHashStringRef(
+                         getShtGroupSignature(ObjSections, Sec)))
+                     .second;
+      if (New && Config->Relocatable)
+        this->Sections[I] = createInputSection(Sec, SectionStringTable);
+      else
+        this->Sections[I] = &InputSection::Discarded;
+      if (New)
         continue;
+
       for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
         if (SecIndex >= Size)
           fatal(toString(this) +
@@ -317,6 +328,7 @@ void elf::ObjectFile<ELFT>::initializeSe
         this->Sections[SecIndex] = &InputSection::Discarded;
       }
       break;
+    }
     case SHT_SYMTAB:
       this->initSymtab(ObjSections, &Sec);
       break;

Modified: vendor/lld/dist/ELF/InputSection.cpp
==============================================================================
--- vendor/lld/dist/ELF/InputSection.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/InputSection.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -23,6 +23,7 @@
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Threading.h"
 #include <mutex>
 
 using namespace llvm;
@@ -172,7 +173,8 @@ void InputSectionBase::uncompress() {
   if (Error E = Dec.decompress({OutputBuf, Size}))
     fatal(toString(this) +
           ": decompress failed: " + llvm::toString(std::move(E)));
-  Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size);
+  this->Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size);
+  this->Flags &= ~(uint64_t)SHF_COMPRESSED;
 }
 
 uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const {
@@ -293,6 +295,24 @@ bool InputSectionBase::classof(const Sec
   return S->kind() != Output;
 }
 
+void InputSection::copyShtGroup(uint8_t *Buf) {
+  assert(this->Type == SHT_GROUP);
+
+  ArrayRef<uint32_t> From = getDataAs<uint32_t>();
+  uint32_t *To = reinterpret_cast<uint32_t *>(Buf);
+
+  // First entry is a flag word, we leave it unchanged.
+  *To++ = From[0];
+
+  // Here we adjust indices of sections that belong to group as it
+  // might change during linking.
+  ArrayRef<InputSectionBase *> Sections = this->File->getSections();
+  for (uint32_t Val : From.slice(1)) {
+    uint32_t Index = read32(&Val, Config->Endianness);
+    write32(To++, Sections[Index]->OutSec->SectionIndex, Config->Endianness);
+  }
+}
+
 InputSectionBase *InputSection::getRelocatedSection() {
   assert(this->Type == SHT_RELA || this->Type == SHT_REL);
   ArrayRef<InputSectionBase *> Sections = this->File->getSections();
@@ -678,6 +698,13 @@ template <class ELFT> void InputSection:
     return;
   }
 
+  // If -r is given, linker should keep SHT_GROUP sections. We should fixup
+  // them, see copyShtGroup().
+  if (this->Type == SHT_GROUP) {
+    copyShtGroup(Buf + OutSecOff);
+    return;
+  }
+
   // Copy section contents from source object file to output file
   // and then apply relocations.
   memcpy(Buf + OutSecOff, Data.data(), Data.size());
@@ -866,7 +893,7 @@ const SectionPiece *MergeInputSection::g
 // it is not just an addition to a base output offset.
 uint64_t MergeInputSection::getOffset(uint64_t Offset) const {
   // Initialize OffsetMap lazily.
-  std::call_once(InitOffsetMap, [&] {
+  llvm::call_once(InitOffsetMap, [&] {
     OffsetMap.reserve(Pieces.size());
     for (const SectionPiece &Piece : Pieces)
       OffsetMap[Piece.InputOff] = Piece.OutputOff;

Modified: vendor/lld/dist/ELF/InputSection.h
==============================================================================
--- vendor/lld/dist/ELF/InputSection.h	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/InputSection.h	Mon May 29 16:26:20 2017	(r319148)
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Object/ELF.h"
+#include "llvm/Support/Threading.h"
 #include <mutex>
 
 namespace lld {
@@ -248,7 +249,7 @@ private:
   std::vector<uint32_t> Hashes;
 
   mutable llvm::DenseMap<uint64_t, uint64_t> OffsetMap;
-  mutable std::once_flag InitOffsetMap;
+  mutable llvm::once_flag InitOffsetMap;
 
   llvm::DenseSet<uint64_t> LiveOffsets;
 };
@@ -318,6 +319,8 @@ public:
 private:
   template <class ELFT, class RelTy>
   void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
+
+  void copyShtGroup(uint8_t *Buf);
 };
 
 // The list of all input sections.

Modified: vendor/lld/dist/ELF/LTO.cpp
==============================================================================
--- vendor/lld/dist/ELF/LTO.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/LTO.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -73,7 +73,12 @@ static std::unique_ptr<lto::LTO> createL
   Conf.Options = InitTargetOptionsFromCodeGenFlags();
   Conf.Options.RelaxELFRelocations = true;
 
-  Conf.RelocModel = Config->Pic ? Reloc::PIC_ : Reloc::Static;
+  if (Config->Relocatable)
+    Conf.RelocModel = None;
+  else if (Config->Pic)
+    Conf.RelocModel = Reloc::PIC_;
+  else
+    Conf.RelocModel = Reloc::Static;
   Conf.CodeModel = GetCodeModelFromCMModel();
   Conf.DisableVerify = Config->DisableVerify;
   Conf.DiagHandler = diagnosticHandler;

Modified: vendor/lld/dist/ELF/LinkerScript.cpp
==============================================================================
--- vendor/lld/dist/ELF/LinkerScript.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/LinkerScript.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -20,6 +20,8 @@
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
+#include "Target.h"
+#include "Threads.h"
 #include "Writer.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
@@ -198,6 +200,15 @@ bool OutputSectionCommand::classof(const
   return C->Kind == OutputSectionKind;
 }
 
+// Fill [Buf, Buf + Size) with Filler.
+// This is used for linker script "=fillexp" command.
+static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
+  size_t I = 0;
+  for (; I + 4 < Size; I += 4)
+    memcpy(Buf + I, &Filler, 4);
+  memcpy(Buf + I, &Filler, Size - I);
+}
+
 bool InputSectionDescription::classof(const BaseCommand *C) {
   return C->Kind == InputSectionKind;
 }
@@ -263,16 +274,16 @@ static bool matchConstraints(ArrayRef<In
          (!IsRW && Kind == ConstraintKind::ReadOnly);
 }
 
-static void sortSections(InputSectionBase **Begin, InputSectionBase **End,
+static void sortSections(InputSection **Begin, InputSection **End,
                          SortSectionPolicy K) {
   if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None)
     std::stable_sort(Begin, End, getComparator(K));
 }
 
 // Compute and remember which sections the InputSectionDescription matches.
-std::vector<InputSectionBase *>
+std::vector<InputSection *>
 LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {
-  std::vector<InputSectionBase *> Ret;
+  std::vector<InputSection *> Ret;
 
   // Collects all sections that satisfy constraints of Cmd.
   for (const SectionPattern &Pat : Cmd->SectionPatterns) {
@@ -294,7 +305,7 @@ LinkerScript::computeInputSections(const
           !Pat.SectionPat.match(Sec->Name))
         continue;
 
-      Ret.push_back(Sec);
+      Ret.push_back(cast<InputSection>(Sec));
       Sec->Assigned = true;
     }
 
@@ -309,8 +320,8 @@ LinkerScript::computeInputSections(const
     //    --sort-section is handled as an inner SORT command.
     // 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
     // 4. If no SORT command is given, sort according to --sort-section.
-    InputSectionBase **Begin = Ret.data() + SizeBefore;
-    InputSectionBase **End = Ret.data() + Ret.size();
+    InputSection **Begin = Ret.data() + SizeBefore;
+    InputSection **End = Ret.data() + Ret.size();
     if (Pat.SortOuter != SortSectionPolicy::None) {
       if (Pat.SortInner == SortSectionPolicy::Default)
         sortSections(Begin, End, Config->SortSection);
@@ -493,7 +504,7 @@ void LinkerScript::addOrphanSections(Out
         Sec->SectionIndex = Index;
       }
       auto *ISD = make<InputSectionDescription>("");
-      ISD->Sections.push_back(S);
+      ISD->Sections.push_back(cast<InputSection>(S));
       Cmd->Commands.push_back(ISD);
     }
   }
@@ -684,7 +695,6 @@ void LinkerScript::adjustSectionsBeforeS
   // '.' is assigned to, but creating these section should not have any bad
   // consequeces and gives us a section to put the symbol in.
   uint64_t Flags = SHF_ALLOC;
-  uint32_t Type = SHT_PROGBITS;
 
   for (int I = 0, E = Opt.Commands.size(); I != E; ++I) {
     auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]);
@@ -692,14 +702,13 @@ void LinkerScript::adjustSectionsBeforeS
       continue;
     if (OutputSection *Sec = Cmd->Sec) {
       Flags = Sec->Flags;
-      Type = Sec->Type;
       continue;
     }
 
     if (isAllSectionDescription(*Cmd))
       continue;
 
-    auto *OutSec = make<OutputSection>(Cmd->Name, Type, Flags);
+    auto *OutSec = make<OutputSection>(Cmd->Name, SHT_PROGBITS, Flags);
     OutSec->SectionIndex = I;
     OutputSections->push_back(OutSec);
     Cmd->Sec = OutSec;
@@ -875,20 +884,20 @@ void LinkerScript::synchronize() {
     if (!Cmd)
       continue;
     ArrayRef<InputSection *> Sections = Cmd->Sec->Sections;
-    std::vector<InputSectionBase **> ScriptSections;
-    DenseSet<InputSectionBase *> ScriptSectionsSet;
+    std::vector<InputSection **> ScriptSections;
+    DenseSet<InputSection *> ScriptSectionsSet;
     for (BaseCommand *Base : Cmd->Commands) {
       auto *ISD = dyn_cast<InputSectionDescription>(Base);
       if (!ISD)
         continue;
-      for (InputSectionBase *&IS : ISD->Sections) {
+      for (InputSection *&IS : ISD->Sections) {
         if (IS->Live) {
           ScriptSections.push_back(&IS);
           ScriptSectionsSet.insert(IS);
         }
       }
     }
-    std::vector<InputSectionBase *> Missing;
+    std::vector<InputSection *> Missing;
     for (InputSection *IS : Sections)
       if (!ScriptSectionsSet.count(IS))
         Missing.push_back(IS);
@@ -896,7 +905,7 @@ void LinkerScript::synchronize() {
       auto ISD = make<InputSectionDescription>("");
       ISD->Sections = Missing;
       Cmd->Commands.push_back(ISD);
-      for (InputSectionBase *&IS : ISD->Sections)
+      for (InputSection *&IS : ISD->Sections)
         if (IS->Live)
           ScriptSections.push_back(&IS);
     }
@@ -1034,10 +1043,12 @@ OutputSectionCommand *LinkerScript::getC
   return I->second;
 }
 
-Optional<uint32_t> LinkerScript::getFiller(OutputSection *Sec) {
-  if (OutputSectionCommand *Cmd = getCmd(Sec))
-    return Cmd->Filler;
-  return None;
+uint32_t OutputSectionCommand::getFiller() {
+  if (Filler)
+    return *Filler;
+  if (Sec->Flags & SHF_EXECINSTR)
+    return Target->TrapInstr;
+  return 0;
 }
 
 static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
@@ -1053,11 +1064,45 @@ static void writeInt(uint8_t *Buf, uint6
     llvm_unreachable("unsupported Size argument");
 }
 
-void LinkerScript::writeDataBytes(OutputSection *Sec, uint8_t *Buf) {
-  if (OutputSectionCommand *Cmd = getCmd(Sec))
-    for (BaseCommand *Base : Cmd->Commands)
-      if (auto *Data = dyn_cast<BytesDataCommand>(Base))
-        writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
+template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
+  Sec->Loc = Buf;
+
+  // We may have already rendered compressed content when using
+  // -compress-debug-sections option. Write it together with header.
+  if (!Sec->CompressedData.empty()) {
+    memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size());
+    memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(),
+           Sec->CompressedData.size());
+    return;
+  }
+
+  // Write leading padding.
+  ArrayRef<InputSection *> Sections = Sec->Sections;
+  uint32_t Filler = getFiller();
+  if (Filler)
+    fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler);
+
+  parallelForEachN(0, Sections.size(), [=](size_t I) {
+    InputSection *IS = Sections[I];
+    IS->writeTo<ELFT>(Buf);
+
+    // Fill gaps between sections.
+    if (Filler) {
+      uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
+      uint8_t *End;
+      if (I + 1 == Sections.size())
+        End = Buf + Sec->Size;
+      else
+        End = Buf + Sections[I + 1]->OutSecOff;
+      fill(Start, End - Start, Filler);
+    }
+  });
+
+  // Linker scripts may have BYTE()-family commands with which you
+  // can write arbitrary bytes to the output. Process them if any.
+  for (BaseCommand *Base : Commands)
+    if (auto *Data = dyn_cast<BytesDataCommand>(Base))
+      writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
 }
 
 bool LinkerScript::hasLMA(OutputSection *Sec) {
@@ -1104,3 +1149,8 @@ size_t LinkerScript::getPhdrIndex(const 
   error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");
   return 0;
 }
+
+template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf);
+template void OutputSectionCommand::writeTo<ELF32BE>(uint8_t *Buf);
+template void OutputSectionCommand::writeTo<ELF64LE>(uint8_t *Buf);
+template void OutputSectionCommand::writeTo<ELF64BE>(uint8_t *Buf);

Modified: vendor/lld/dist/ELF/LinkerScript.h
==============================================================================
--- vendor/lld/dist/ELF/LinkerScript.h	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/LinkerScript.h	Mon May 29 16:26:20 2017	(r319148)
@@ -130,6 +130,9 @@ struct OutputSectionCommand : BaseComman
   ConstraintKind Constraint = ConstraintKind::NoConstraint;
   std::string Location;
   std::string MemoryRegionName;
+
+  template <class ELFT> void writeTo(uint8_t *Buf);
+  uint32_t getFiller();
 };
 
 // This struct represents one section match pattern in SECTIONS() command.
@@ -157,7 +160,7 @@ struct InputSectionDescription : BaseCom
   // will be associated with this InputSectionDescription.
   std::vector<SectionPattern> SectionPatterns;
 
-  std::vector<InputSectionBase *> Sections;
+  std::vector<InputSection *> Sections;
 };
 
 // Represents an ASSERT().
@@ -213,11 +216,10 @@ struct ScriptConfiguration {
 
 class LinkerScript final {
   llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
-  OutputSectionCommand *getCmd(OutputSection *Sec) const;
   void assignSymbol(SymbolAssignment *Cmd, bool InSec);
   void setDot(Expr E, const Twine &Loc, bool InSec);
 
-  std::vector<InputSectionBase *>
+  std::vector<InputSection *>
   computeInputSections(const InputSectionDescription *);
 
   std::vector<InputSectionBase *>
@@ -244,6 +246,7 @@ class LinkerScript final {
   MemoryRegion *CurMemRegion = nullptr;
 
 public:
+  OutputSectionCommand *getCmd(OutputSection *Sec) const;
   bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
   uint64_t getDot() { return Dot; }
   OutputSection *getOutputSection(const Twine &Loc, StringRef S);
@@ -263,7 +266,6 @@ public:
   std::vector<PhdrEntry> createPhdrs();
   bool ignoreInterpSection();
 
-  llvm::Optional<uint32_t> getFiller(OutputSection *Sec);
   bool hasLMA(OutputSection *Sec);
   bool shouldKeep(InputSectionBase *S);
   void assignOffsets(OutputSectionCommand *Cmd);
@@ -272,7 +274,6 @@ public:
   void synchronize();
   void assignAddresses(std::vector<PhdrEntry> &Phdrs);
 
-  void writeDataBytes(OutputSection *Sec, uint8_t *Buf);
   void addSymbol(SymbolAssignment *Cmd);
   void processCommands(OutputSectionFactory &Factory);
 

Modified: vendor/lld/dist/ELF/MapFile.cpp
==============================================================================
--- vendor/lld/dist/ELF/MapFile.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/MapFile.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -132,12 +132,17 @@ void elf::writeMapFile(llvm::ArrayRef<Ba
     OS << OSec->Name << '\n';
 
     // Dump symbols for each input section.
-    for (InputSection *IS : OSec->Sections) {
-      writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(),
-                        IS->Alignment);
-      OS << indent(1) << toString(IS) << '\n';
-      for (DefinedRegular *Sym : SectionSyms[IS])
-        OS << SymStr[Sym] << '\n';
+    for (BaseCommand *Base : Cmd->Commands) {
+      auto *ISD = dyn_cast<InputSectionDescription>(Base);
+      if (!ISD)
+        continue;
+      for (InputSection *IS : ISD->Sections) {
+        writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(),
+                          IS->Alignment);
+        OS << indent(1) << toString(IS) << '\n';
+        for (DefinedRegular *Sym : SectionSyms[IS])
+          OS << SymStr[Sym] << '\n';
+      }
     }
   }
 }

Modified: vendor/lld/dist/ELF/Options.td
==============================================================================
--- vendor/lld/dist/ELF/Options.td	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/Options.td	Mon May 29 16:26:20 2017	(r319148)
@@ -313,6 +313,7 @@ def alias_o_output2 : Separate<["--"], "
 def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>;
 def alias_print_map_M: Flag<["-"], "M">, Alias<print_map>;
 def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>;
+def alias_reproduce_eq: J<"reproduce=">, Alias<reproduce>;
 def alias_retain_symbols_file: S<"retain-symbols-file">, Alias<retain_symbols_file>;
 def alias_rpath_R: JoinedOrSeparate<["-"], "R">, Alias<rpath>;
 def alias_rpath_rpath: J<"rpath=">, Alias<rpath>;

Modified: vendor/lld/dist/ELF/OutputSections.cpp
==============================================================================
--- vendor/lld/dist/ELF/OutputSections.cpp	Mon May 29 16:26:16 2017	(r319147)
+++ vendor/lld/dist/ELF/OutputSections.cpp	Mon May 29 16:26:20 2017	(r319148)
@@ -103,7 +103,7 @@ template <class ELFT> void OutputSection
 
   // Write section contents to a temporary buffer and compress it.
   std::vector<uint8_t> Buf(Size);
-  writeTo<ELFT>(Buf.data());
+  Script->getCmd(this)->writeTo<ELFT>(Buf.data());
   if (Error E = zlib::compress(toStringRef(Buf), CompressedData))
     fatal("compress failed: " + llvm::toString(std::move(E)));
 
@@ -112,6 +112,19 @@ template <class ELFT> void OutputSection
   Flags |= SHF_COMPRESSED;
 }
 
+template <class ELFT> static void finalizeShtGroup(OutputSection *Sec) {
+  // sh_link field for SHT_GROUP sections should contain the section index of
+  // the symbol table.
+  Sec->Link = InX::SymTab->OutSec->SectionIndex;
+
+  // sh_link then contain index of an entry in symbol table section which
+  // provides signature of the section group.
+  elf::ObjectFile<ELFT> *Obj = Sec->Sections[0]->getFile<ELFT>();
+  assert(Config->Relocatable && Sec->Sections.size() == 1);
+  ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
+  Sec->Info = InX::SymTab->getSymbolIndex(Symbols[Sec->Sections[0]->Info - 1]);
+}
+
 template <class ELFT> void OutputSection::finalize() {
   if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) {
     std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
@@ -126,6 +139,11 @@ template <class ELFT> void OutputSection
   }
 
   uint32_t Type = this->Type;
+  if (Type == SHT_GROUP) {
+    finalizeShtGroup<ELFT>(this);
+    return;
+  }
+
   if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
     return;
 
@@ -259,69 +277,6 @@ void OutputSection::sortCtorsDtors() {
   std::stable_sort(Sections.begin(), Sections.end(), compCtors);
 }
 
-// Fill [Buf, Buf + Size) with Filler.
-// This is used for linker script "=fillexp" command.
-static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
-  size_t I = 0;
-  for (; I + 4 < Size; I += 4)
-    memcpy(Buf + I, &Filler, 4);
-  memcpy(Buf + I, &Filler, Size - I);
-}
-
-uint32_t OutputSection::getFiller() {
-  // Determine what to fill gaps between InputSections with, as specified by the
-  // linker script. If nothing is specified and this is an executable section,
-  // fall back to trap instructions to prevent bad diassembly and detect invalid
-  // jumps to padding.
-  if (Optional<uint32_t> Filler = Script->getFiller(this))
-    return *Filler;
-  if (Flags & SHF_EXECINSTR)
-    return Target->TrapInstr;
-  return 0;
-}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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