Add DT_REL(A)COUNT tag to .dynamic section

This patch groups relative relocations in a single block
in combrelocs mode and adds DT_RELCOUNT or DT_RELACOUNT
tag to .dynamic section

Differential revision: https://reviews.llvm.org/D23661

llvm-svn: 280210
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 05c4fa9..37fc054 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -354,11 +354,18 @@
 
 template <class ELFT>
 void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) {
+  if (Reloc.Type == Target->RelativeRel)
+    ++NumRelativeRelocs;
   Relocs.push_back(Reloc);
 }
 
 template <class ELFT, class RelTy>
 static bool compRelocations(const RelTy &A, const RelTy &B) {
+  bool AIsRel = A.getType(Config->Mips64EL) == Target->RelativeRel;
+  bool BIsRel = B.getType(Config->Mips64EL) == Target->RelativeRel;
+  if (AIsRel != BIsRel)
+    return AIsRel;
+
   return A.getSymbol(Config->Mips64EL) < B.getSymbol(Config->Mips64EL);
 }
 
@@ -661,6 +668,10 @@
     Add({IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize()});
     Add({IsRela ? DT_RELAENT : DT_RELENT,
          uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))});
+
+    size_t NumRelativeRels = Out<ELFT>::RelaDyn->getRelativeRelocCount();
+    if (Config->ZCombreloc && NumRelativeRels)
+      Add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels});
   }
   if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
     Add({DT_JMPREL, Out<ELFT>::RelaPlt});