summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2015-12-03 02:23:33 +0000
committerRui Ueyama <ruiu@google.com>2015-12-03 02:23:33 +0000
commit43e12900d9e843d0b55557f99312c547037b7dc4 (patch)
treebdc07dbc0ee592cc82610903bedf4ddb02d005a5
parentd35fe3d984500ee57f97b1c62bc653c231bc643b (diff)
downloadbcm5719-llvm-43e12900d9e843d0b55557f99312c547037b7dc4.tar.gz
bcm5719-llvm-43e12900d9e843d0b55557f99312c547037b7dc4.zip
COFF: Non-external COMDAT sections sholud not be merged by ICF.
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
-rw-r--r--lld/COFF/Chunks.h3
-rw-r--r--lld/COFF/ICF.cpp3
-rw-r--r--lld/test/COFF/icf-local.test66
3 files changed, 69 insertions, 3 deletions
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 7f6d06198c8..60b8e76f823 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -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;
};
diff --git a/lld/COFF/ICF.cpp b/lld/COFF/ICF.cpp
index 3dab8a79ed6..f99b41624a8 100644
--- a/lld/COFF/ICF.cpp
+++ b/lld/COFF/ICF.cpp
@@ -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
index 00000000000..a0b4c91559a
--- /dev/null
+++ b/lld/test/COFF/icf-local.test
@@ -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
+...
OpenPOWER on IntegriCloud