COFF: Non-external COMDAT sections sholud not be merged by ICF.
authorRui Ueyama <ruiu@google.com>
Thu, 3 Dec 2015 02:23:33 +0000 (02:23 +0000)
committerRui Ueyama <ruiu@google.com>
Thu, 3 Dec 2015 02:23:33 +0000 (02:23 +0000)
If a section symbol is not external, that COMDAT section should never
be merge with other sections in other compilation unit. Previously,
we didn't take visibility into account.

Note that COMDAT sections with non-external visibility makes sense
because they can be removed by dead-stripping.

Fixes https://llvm.org/bugs/show_bug.cgi?id=25686

llvm-svn: 254578

lld/COFF/Chunks.h
lld/COFF/ICF.cpp
lld/test/COFF/icf-local.test [new file with mode: 0644]

index 7f6d061..60b8e76 100644 (file)
@@ -204,8 +204,7 @@ private:
   void replace(SectionChunk *Other);
   std::atomic<uint64_t> GroupID = { 0 };
 
-  // Chunks are basically unnamed chunks of bytes.
-  // Symbols are associated for debugging and logging purposs only.
+  // Sym points to a section symbol if this is a COMDAT chunk.
   DefinedRegular *Sym = nullptr;
 };
 
index 3dab8a7..f99b416 100644 (file)
@@ -185,8 +185,9 @@ void ICF::run(const std::vector<Chunk *> &Vec) {
   // Collect only mergeable sections and group by hash value.
   parallel_for_each(Vec.begin(), Vec.end(), [&](Chunk *C) {
     if (auto *SC = dyn_cast<SectionChunk>(C)) {
+      bool Global = SC->Sym && SC->Sym->isExternal();
       bool Writable = SC->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
-      if (SC->isCOMDAT() && SC->isLive() && !Writable)
+      if (SC->isCOMDAT() && SC->isLive() && Global && !Writable)
         SC->GroupID = getHash(SC) | (uint64_t(1) << 63);
     }
   });
diff --git a/lld/test/COFF/icf-local.test b/lld/test/COFF/icf-local.test
new file mode 100644 (file)
index 0000000..a0b4c91
--- /dev/null
@@ -0,0 +1,66 @@
+# COMDAT sections with non-external linkage should not be merged by ICF.
+
+# RUN: yaml2obj < %s > %t1.obj
+# RUN: sed s/foo/main/ %s | yaml2obj > %t2.obj
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /verbose \
+# RUN:   %t1.obj %t2.obj > %t.log 2>&1
+# RUN: FileCheck %s < %t.log
+
+# CHECK-NOT: Removed bar
+
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       16
+    SectionData:     488D0500000000C3
+    Relocations:
+      - VirtualAddress:  3
+        SymbolName:      bar
+        Type:            IMAGE_REL_AMD64_REL32
+  - Name:            .rdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ]
+    Alignment:       8
+    SectionData:     2A000000000000002B00000000000000
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          8
+      NumberOfRelocations: 1
+      NumberOfLinenumbers: 0
+      CheckSum:        1092178131
+      Number:          1
+  - Name:            .rdata
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          16
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        1200668497
+      Number:          5
+      Selection:       IMAGE_COMDAT_SELECT_ANY
+  - Name:            foo
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            bar
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+...