[ELF] - Do not merge sections from SHT_GROUP when -relocatable
authorGeorge Rimar <grimar@accesssoftek.com>
Tue, 19 Sep 2017 09:40:31 +0000 (09:40 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Tue, 19 Sep 2017 09:40:31 +0000 (09:40 +0000)
This is PR34506.

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

.section        .foo,"axG",@progbits,bar,comdat
.section        .foo,"axG",@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, preventing merging SHF_GROUP sections with any others.

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

llvm-svn: 313621

lld/ELF/OutputSections.cpp
lld/test/ELF/relocatable-comdat2.s [new file with mode: 0644]

index 148b79e..f9a4b84 100644 (file)
@@ -251,12 +251,14 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
     return;
   }
 
-  // Sections with the SHT_GROUP attribute reach here only when the -r option
-  // is given. Such sections define "section groups", and InputFiles.cpp has
-  // 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) {
+  // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
+  // option is given. A section with SHT_GROUP defines a "section group", and
+  // its members have SHF_GROUP attribute. Usually these flags have already been
+  // stripped by InputFiles.cpp as section groups are processed and uniquified.
+  // However, for the -r option, we want to pass through all section groups
+  // as-is because adding/removing members or merging them with other groups
+  // change their semantics.
+  if (IS->Type == SHT_GROUP || (IS->Flags & SHF_GROUP)) {
     addSection(IS, OutsecName, nullptr);
     return;
   }
diff --git a/lld/test/ELF/relocatable-comdat2.s b/lld/test/ELF/relocatable-comdat2.s
new file mode 100644 (file)
index 0000000..2643e64
--- /dev/null
@@ -0,0 +1,35 @@
+# 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 -s %t | FileCheck %s
+
+## Check .foo was not merged.
+# CHECK: Sections [
+# CHECK:  Name: .foo
+# CHECK:  Name: .foo
+# CHECK:  Name: .foo
+
+# 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",@progbits,bar,comdat
+.section .foo,"axG",@progbits,zed,comdat
+.section .foo,"ax",@progbits