Add support for merging string from SHF_STRINGS sections.

llvm-svn: 251212
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 9aa207b..b2142b7 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -121,6 +121,33 @@
 }
 
 template <class ELFT>
+static bool shouldMerge(const typename ELFFile<ELFT>::Elf_Shdr &Sec) {
+  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+  uintX_t Flags = Sec.sh_flags;
+  if (!(Flags & SHF_MERGE))
+    return false;
+  if (Flags & SHF_WRITE)
+    error("Writable SHF_MERGE sections are not supported");
+  uintX_t EntSize = Sec.sh_entsize;
+  if (Sec.sh_size % EntSize)
+    error("SHF_MERGE section size must be a multiple of sh_entsize");
+
+  // Don't try to merge if the aligment is larger than the sh_entsize.
+  //
+  // If this is not a SHF_STRINGS, we would need to pad after every entity. It
+  // would be equivalent for the producer of the .o to just set a larger
+  // sh_entsize.
+  //
+  // If this is a SHF_STRINGS, the larger alignment makes sense. Unfortunately
+  // it would complicate tail merging. This doesn't seem that common to
+  // justify the effort.
+  if (Sec.sh_addralign > EntSize)
+    return false;
+
+  return true;
+}
+
+template <class ELFT>
 void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) {
   uint64_t Size = this->ELFObj.getNumSections();
   Sections.resize(Size);
@@ -170,18 +197,13 @@
         error("Relocations pointing to SHF_MERGE are not supported");
       break;
     }
-    default: {
-      uintX_t Flags = Sec.sh_flags;
-      if (Flags & SHF_MERGE && !(Flags & SHF_STRINGS)) {
-        if (Flags & SHF_WRITE)
-          error("Writable SHF_MERGE sections are not supported");
+    default:
+      if (shouldMerge<ELFT>(Sec))
         Sections[I] = new (this->Alloc) MergeInputSection<ELFT>(this, &Sec);
-      } else {
+      else
         Sections[I] = new (this->Alloc) InputSection<ELFT>(this, &Sec);
-      }
       break;
     }
-    }
   }
 }