diff options
| author | Rui Ueyama <ruiu@google.com> | 2015-12-03 02:23:33 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2015-12-03 02:23:33 +0000 |
| commit | 43e12900d9e843d0b55557f99312c547037b7dc4 (patch) | |
| tree | bdc07dbc0ee592cc82610903bedf4ddb02d005a5 | |
| parent | d35fe3d984500ee57f97b1c62bc653c231bc643b (diff) | |
| download | bcm5719-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.h | 3 | ||||
| -rw-r--r-- | lld/COFF/ICF.cpp | 3 | ||||
| -rw-r--r-- | lld/test/COFF/icf-local.test | 66 |
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 +... |

