[PATCH] D37574: [ELF] - Do not merge sections from SHT_GROUP when -relocatable

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 7 08:59:13 PDT 2017


grimar created this revision.
Herald added a subscriber: emaste.

This is PR34506.

Imagine we have 2 sections the same name but different COMDAT groups:

  .section        .foo,"axG", at progbits,bar,comdat
  .section        .foo,"axG", at progbits,zed,comdat

When linking relocatable we do not merge SHT_GROUP sections. But still would merge
both input sections `.foo` into single output section `.foo`.
As a result we will have 2 different SHT_GROUPs containing the same section, what
is wrong.

Patch fixes the issue, keeping a set of all sections belonging to group for file
and making a unique output section for each.


https://reviews.llvm.org/D37574

Files:
  ELF/InputFiles.cpp
  ELF/InputFiles.h
  ELF/OutputSections.cpp
  test/ELF/relocatable-comdat2.s


Index: test/ELF/relocatable-comdat2.s
===================================================================
--- test/ELF/relocatable-comdat2.s
+++ test/ELF/relocatable-comdat2.s
@@ -0,0 +1,28 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld -r %t.o -o %t
+# RUN: llvm-readobj -elf-section-groups %t | FileCheck %s
+
+# CHECK:      Groups {
+# CHECK-NEXT:   Group {
+# CHECK-NEXT:     Name: .group
+# CHECK-NEXT:     Index: 2
+# CHECK-NEXT:     Type: COMDAT
+# CHECK-NEXT:     Signature: bar
+# CHECK-NEXT:     Section(s) in group [
+# CHECK-NEXT:       .foo (3)
+# CHECK-NEXT:     ]
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Group {
+# CHECK-NEXT:     Name: .group
+# CHECK-NEXT:     Index: 4
+# CHECK-NEXT:     Type: COMDAT
+# CHECK-NEXT:     Signature: zed
+# CHECK-NEXT:     Section(s) in group [
+# CHECK-NEXT:       .foo (5)
+# CHECK-NEXT:     ]
+# CHECK-NEXT:   }
+# CHECK-NEXT: }
+
+.section .foo,"axG", at progbits,bar,comdat
+.section .foo,"axG", at progbits,zed,comdat
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -212,7 +212,10 @@
   // dedup'ed section groups by their signatures. For the -r, we want to pass
   // through all SHT_GROUP sections without merging them because merging them
   // creates broken section contents.
-  if (IS->Type == SHT_GROUP) {
+  // We also do not merge any sections belonging to groups because otherwise we
+  // end up with multiple SHT_GROUPs containing the same output section.
+  if (IS->Type == SHT_GROUP ||
+      (IS->File && IS->File->GroupedSections.count(IS))) {
     OutputSection *Out = nullptr;
     addInputSec(IS, OutsecName, Out);
     return;
Index: ELF/InputFiles.h
===================================================================
--- ELF/InputFiles.h
+++ ELF/InputFiles.h
@@ -105,6 +105,10 @@
   // Cache for toString(). Only toString() should use this member.
   mutable std::string ToStringCache;
 
+  // Keeps sections that belongs to COMDAT groups, used for -r. Each section
+  // that belongs to group should be placed to separate output section.
+  llvm::DenseSet<InputSectionBase *> GroupedSections;
+
 protected:
   InputFile(Kind K, MemoryBufferRef M);
   std::vector<InputSectionBase *> Sections;
Index: ELF/InputFiles.cpp
===================================================================
--- ELF/InputFiles.cpp
+++ ELF/InputFiles.cpp
@@ -278,6 +278,7 @@
   this->SectionStringTable =
       check(Obj.getSectionStringTable(ObjSections), toString(this));
 
+  std::vector<const Elf_Shdr *> Groups;
   for (size_t I = 0, E = ObjSections.size(); I < E; I++) {
     if (this->Sections[I] == &InputSection::Discarded)
       continue;
@@ -304,8 +305,10 @@
       // exception is the -r option because in order to produce re-linkable
       // object files, we want to pass through basically everything.
       if (IsNew) {
-        if (Config->Relocatable)
+        if (Config->Relocatable) {
           this->Sections[I] = createInputSection(Sec);
+          Groups.push_back(&Sec);
+        }
         continue;
       }
 
@@ -332,6 +335,10 @@
       this->Sections[I] = createInputSection(Sec);
     }
 
+    for (const Elf_Shdr *Sec : Groups)
+      for (uint32_t Ndx : getShtGroupEntries(*Sec))
+        GroupedSections.insert(this->Sections[Ndx]);
+
     // .ARM.exidx sections have a reverse dependency on the InputSection they
     // have a SHF_LINK_ORDER dependency, this is identified by the sh_link.
     if (Sec.sh_flags & SHF_LINK_ORDER) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D37574.114188.patch
Type: text/x-patch
Size: 3576 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170907/31207747/attachment.bin>


More information about the llvm-commits mailing list