Index: ELF/InputFiles.h
===================================================================
--- ELF/InputFiles.h
+++ ELF/InputFiles.h
@@ -106,6 +106,7 @@
   StringRef getStringTable() const { return StringTable; }
 
   uint32_t getSectionIndex(const Elf_Sym &Sym) const;
+  uint32_t getSectionIndex(unsigned SymIndex) const;
 
   Elf_Sym_Range getElfSymbols(bool OnlyGlobals);
 
@@ -143,6 +144,8 @@
 
   ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
   InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
+  std::vector<InputSectionBase<ELFT> *>
+  getComdatSections(llvm::DenseSet<StringRef> &Signatures) const;
 
   SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
     return *SymbolBodies[SymbolIndex];
@@ -153,6 +156,13 @@
     return getSymbolBody(SymIndex);
   }
 
+  template <typename RelT>
+  uint32_t getRelocSectionIndex(const RelT &Rel) const {
+    return this->getSectionIndex(Rel.getSymbol(Config->Mips64EL));
+  }
+
+  StringRef getComdatGroupSignature(unsigned SecIndex);
+
   const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
 
   // Get MIPS GP0 value defined by this file. This value represents the gp value
@@ -190,6 +200,9 @@
   // MIPS .MIPS.abiflags section defined by this file.
   std::unique_ptr<MipsAbiFlagsInputSection<ELFT>> MipsAbiFlags;
 
+  // Section index to comdat group signature map;
+  llvm::DenseMap<unsigned, StringRef> SectionGroupSig;
+
   llvm::SpecificBumpPtrAllocator<InputSection<ELFT>> IAlloc;
   llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
   llvm::SpecificBumpPtrAllocator<EhInputSection<ELFT>> EHAlloc;
Index: ELF/InputFiles.cpp
===================================================================
--- ELF/InputFiles.cpp
+++ ELF/InputFiles.cpp
@@ -99,6 +99,16 @@
   return I;
 }
 
+template <class ELFT>
+uint32_t ELFFileBase<ELFT>::getSectionIndex(unsigned SymIndex) const {
+  Elf_Sym_Range Syms = ELFObj.symbols(Symtab);
+  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
+  if (SymIndex >= NumSymbols)
+    return -1;
+
+  return getSectionIndex(Syms[SymIndex]);
+}
+
 template <class ELFT> void ELFFileBase<ELFT>::initStringTable() {
   if (!Symtab)
     return;
@@ -218,16 +228,20 @@
     if (Sections[I] == &InputSection<ELFT>::Discarded)
       continue;
 
+    bool NewGroup;
+    StringRef GroupSig;
     switch (Sec.sh_type) {
     case SHT_GROUP:
       Sections[I] = &InputSection<ELFT>::Discarded;
-      if (ComdatGroups.insert(getShtGroupSignature(Sec)).second)
-        continue;
+      GroupSig = getShtGroupSignature(Sec);
+      NewGroup = ComdatGroups.insert(GroupSig).second;
       for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
         if (SecIndex >= Size)
           fatal(getFilename(this) + ": invalid section index in group: " +
                 Twine(SecIndex));
-        Sections[SecIndex] = &InputSection<ELFT>::Discarded;
+        if (!NewGroup)
+          Sections[SecIndex] = &InputSection<ELFT>::Discarded;
+        SectionGroupSig[SecIndex] = GroupSig;
       }
       break;
     case SHT_SYMTAB:
@@ -368,6 +382,23 @@
 }
 
 template <class ELFT>
+std::vector<InputSectionBase<ELFT> *> elf::ObjectFile<ELFT>::getComdatSections(
+    DenseSet<StringRef> &Signatures) const {
+  std::vector<InputSectionBase<ELFT> *> Ret;
+  for (auto &P : SectionGroupSig)
+    if (Signatures.find(P.second) != Signatures.end() &&
+        Sections[P.first] != &InputSectionBase<ELFT>::Discarded)
+      Ret.push_back(Sections[P.first]);
+
+  return Ret;
+}
+
+template <class ELFT>
+StringRef elf::ObjectFile<ELFT>::getComdatGroupSignature(unsigned SecIndex) {
+  return SectionGroupSig[SecIndex];
+}
+
+template <class ELFT>
 SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
   int Binding = Sym->getBinding();
   InputSectionBase<ELFT> *Sec = getSection(*Sym);
Index: ELF/MarkLive.cpp
===================================================================
--- ELF/MarkLive.cpp
+++ ELF/MarkLive.cpp
@@ -43,9 +43,12 @@
 
 namespace {
 // A resolved relocation. The Sec and Offset fields are set if the relocation
-// was resolved to an offset within a section.
+// was resolved to an offset within a section. If relocation was resolved to
+// a member of comdat group then Sec may be null and Offset is an index of
+// section in File.
 template <class ELFT>
 struct ResolvedReloc {
+  ObjectFile<ELFT> *File;
   InputSectionBase<ELFT> *Sec;
   typename ELFT::uint Offset;
 };
@@ -70,11 +73,13 @@
   SymbolBody &B = Sec.getFile()->getRelocTargetSym(Rel);
   auto *D = dyn_cast<DefinedRegular<ELFT>>(&B);
   if (!D || !D->Section)
-    return {nullptr, 0};
+    return {nullptr, nullptr, 0};
+  if (D->Section == &InputSectionBase<ELFT>::Discarded)
+    return {Sec.getFile(), nullptr, Sec.getFile()->getRelocSectionIndex(Rel)};
   typename ELFT::uint Offset = D->Value;
   if (D->isSection())
     Offset += getAddend(Sec, Rel);
-  return {D->Section->Repl, Offset};
+  return {D->Section->Repl->getFile(), D->Section->Repl, Offset};
 }
 
 // Calls Fn for each section that Sec refers to via relocations.
@@ -136,7 +141,7 @@
         continue;
       if (R.Sec->getSectionHdr()->sh_flags & SHF_EXECINSTR)
         continue;
-      Enqueue({R.Sec, 0});
+      Enqueue({R.Sec->getFile(), R.Sec, 0});
     }
   }
 }
@@ -187,10 +192,18 @@
 // sections to set their "Live" bits.
 template <class ELFT> void elf::markLive() {
   SmallVector<InputSection<ELFT> *, 256> Q;
+  DenseSet<StringRef> LiveComdatGroups;
 
   auto Enqueue = [&](ResolvedReloc<ELFT> R) {
-    if (!R.Sec)
+    if (!R.Sec) {
+      if (!R.File)
+        return;
+
+      StringRef GroupSig = R.File->getComdatGroupSignature(R.Offset);
+      if (!GroupSig.empty())
+        LiveComdatGroups.insert(GroupSig);
       return;
+    }
 
     // Usually, a whole section is marked as live or dead, but in mergeable
     // (splittable) sections, each piece of data has independent liveness bit.
@@ -207,7 +220,7 @@
 
   auto MarkSymbol = [&](const SymbolBody *Sym) {
     if (auto *D = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym))
-      Enqueue({D->Section, D->Value});
+      Enqueue({D->Section->getFile(), D->Section, D->Value});
   };
 
   // Add GC root symbols.
@@ -235,12 +248,23 @@
         if (auto *EH = dyn_cast_or_null<EhInputSection<ELFT>>(Sec))
           scanEhFrameSection<ELFT>(*EH, Enqueue);
         if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec))
-          Enqueue({Sec, 0});
+          Enqueue({Sec->getFile(), Sec, 0});
       }
     }
   }
 
-  // Mark all reachable sections.
+  // Pass 1. Mark all reachable sections, except comdat groups.
+  while (!Q.empty())
+    forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue);
+
+  if (LiveComdatGroups.empty())
+    return;
+
+  // Pass 2. Identify and mark reachable comdat groups.
+  for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
+    for (InputSectionBase<ELFT> *Sec : F->getComdatSections(LiveComdatGroups))
+      Enqueue({Sec->getFile(), Sec, 0});
+
   while (!Q.empty())
     forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue);
 }
Index: test/ELF/Inputs/comdat-gc.s
===================================================================
--- test/ELF/Inputs/comdat-gc.s
+++ test/ELF/Inputs/comdat-gc.s
@@ -0,0 +1,10 @@
+.weak	_Z3fooIiEvv
+.section	.text._Z3fooIiEvv,"axG",@progbits,_Z3fooIiEvv,comdat
+_Z3fooIiEvv:
+  ret
+
+.global _start
+.section .zzz, "ax"  
+_start:
+   leaq    .text._Z3fooIiEvv(%rip), %rax
+
Index: test/ELF/comdat-gc.s
===================================================================
--- test/ELF/comdat-gc.s
+++ test/ELF/comdat-gc.s
@@ -0,0 +1,13 @@
+// Check that the linker doesn't crash and comdat group is not gc'ed
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/comdat-gc.s -o %t2.o
+// RUN: ld.lld --gc-sections %t.o %t2.o -o %t
+// RUN: llvm-readobj -t %t | FileCheck %s
+// CHECK: _Z3fooIiEvv
+
+.weak	_Z3fooIiEvv
+
+.section	.text._Z3fooIiEvv,"axG",@progbits,_Z3fooIiEvv,comdat
+_Z3fooIiEvv:
+  ret
+