Drop conflicting sh_entsize values.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Nov 2017 17:35:22 +0000 (17:35 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Nov 2017 17:35:22 +0000 (17:35 +0000)
An output section can include elements from two input sections with
different sh_entsize. When that happens the output section itself
should not have a sh_entsize.

llvm-svn: 318311

lld/ELF/OutputSections.cpp
lld/test/ELF/linkerscript/merge-sections.s
lld/test/ELF/merge-entsize.s [new file with mode: 0644]

index 357affe9e223f08f6093c01d3950876a9c4ab4cd..bc67a000e88e5bef4ef106dbaa61c47a95ed0c15 100644 (file)
@@ -91,9 +91,10 @@ static bool canMergeToProgbits(unsigned Type) {
 void OutputSection::addSection(InputSection *IS) {
   if (!Live) {
     // If IS is the first section to be added to this section,
-    // initialize Type by IS->Type.
+    // initialize Type and Entsize from IS.
     Live = true;
     Type = IS->Type;
+    Entsize = IS->Entsize;
   } else {
     // Otherwise, check if new type or flags are compatible with existing ones.
     if ((Flags & (SHF_ALLOC | SHF_TLS)) != (IS->Flags & (SHF_ALLOC | SHF_TLS)))
@@ -124,13 +125,10 @@ void OutputSection::addSection(InputSection *IS) {
   this->Size = IS->OutSecOff + IS->getSize();
 
   // If this section contains a table of fixed-size entries, sh_entsize
-  // holds the element size. Consequently, if this contains two or more
-  // input sections, all of them must have the same sh_entsize. However,
-  // you can put different types of input sections into one output
-  // section by using linker scripts. I don't know what to do here.
-  // Probably we sholuld handle that as an error. But for now we just
-  // pick the largest sh_entsize.
-  this->Entsize = std::max(this->Entsize, IS->Entsize);
+  // holds the element size. If it contains elements of different size we
+  // set sh_entsize to 0.
+  if (Entsize != IS->Entsize)
+    Entsize = 0;
 
   if (!IS->Assigned) {
     IS->Assigned = true;
index f93c15f855e8378632b57e069582b0c6b09a4662..950d822ec4039e12f434df203b1fc5a7ca045eb2 100644 (file)
@@ -21,7 +21,7 @@
 # CHECK-NEXT:   Link: 0
 # CHECK-NEXT:   Info: 0
 # CHECK-NEXT:   AddressAlignment: 2
-# CHECK-NEXT:   EntrySize: 2
+# CHECK-NEXT:   EntrySize: 0
 # CHECK-NEXT: }
 
 # CHECK:      Name: begin
diff --git a/lld/test/ELF/merge-entsize.s b/lld/test/ELF/merge-entsize.s
new file mode 100644 (file)
index 0000000..c2e41cc
--- /dev/null
@@ -0,0 +1,27 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -s %t | FileCheck %s
+
+        .section  .rodata.1,"aM",@progbits,1
+        .byte 0x42
+
+        .section  .rodata.2,"aM",@progbits,2
+        .short 0x42
+
+// Since the output section has both .rodata.1 and .rodata.2, it
+// contains elements of different sizes and we use an entsize of 0.
+
+// CHECK:      Name: .rodata (
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT:   SHF_ALLOC
+// CHECK-NEXT:   SHF_MERGE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize: 0