Index: lld/COFF/Chunks.h =================================================================== --- lld/COFF/Chunks.h +++ lld/COFF/Chunks.h @@ -311,6 +311,10 @@ // Auxiliary Format 5: Section Definitions. Used for ICF. uint32_t checksum = 0; + // The section chunk length as defined in the section aux definition, + // if available. + uint32_t sectionDefLength = 0; + // Used by the garbage collector. bool live; Index: lld/COFF/Chunks.cpp =================================================================== --- lld/COFF/Chunks.cpp +++ lld/COFF/Chunks.cpp @@ -55,7 +55,7 @@ // SectionChunk is one of the most frequently allocated classes, so it is // important to keep it as compact as possible. As of this writing, the number // below is the size of this class on x64 platforms. -static_assert(sizeof(SectionChunk) <= 88, "SectionChunk grew unexpectedly"); +static_assert(sizeof(SectionChunk) <= 96, "SectionChunk grew unexpectedly"); static void add16(uint8_t *p, int16_t v) { write16le(p, read16le(p) + v); } static void add32(uint8_t *p, int32_t v) { write32le(p, read32le(p) + v); } Index: lld/COFF/InputFiles.h =================================================================== --- lld/COFF/InputFiles.h +++ lld/COFF/InputFiles.h @@ -255,9 +255,10 @@ // match the existing symbol and its selection. If either old or new // symbol have selection IMAGE_COMDAT_SELECT_LARGEST, Sym might replace // the existing leader. In that case, Prevailing is set to true. - void handleComdatSelection(COFFSymbolRef sym, - llvm::COFF::COMDATType &selection, - bool &prevailing, DefinedRegular *leader); + void + handleComdatSelection(COFFSymbolRef sym, llvm::COFF::COMDATType &selection, + bool &prevailing, DefinedRegular *leader, + const llvm::object::coff_aux_section_definition *def); llvm::Optional createDefined(COFFSymbolRef sym, Index: lld/COFF/InputFiles.cpp =================================================================== --- lld/COFF/InputFiles.cpp +++ lld/COFF/InputFiles.cpp @@ -275,8 +275,10 @@ if (sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) return nullptr; auto *c = make(this, sec); - if (def) + if (def) { c->checksum = def->CheckSum; + c->sectionDefLength = def->Length; + } // CodeView sections are stored to a different vector because they are not // linked in the regular manner. @@ -476,8 +478,10 @@ return symtab->addUndefined(name, this, sym.isWeakExternal()); } -void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection, - bool &prevailing, DefinedRegular *leader) { +void ObjFile::handleComdatSelection( + COFFSymbolRef sym, COMDATType &selection, bool &prevailing, + DefinedRegular *leader, + const llvm::object::coff_aux_section_definition *def) { if (prevailing) return; // There's already an existing comdat for this symbol: `Leader`. @@ -544,8 +548,10 @@ break; case IMAGE_COMDAT_SELECT_SAME_SIZE: - if (leaderChunk->getSize() != getSection(sym)->SizeOfRawData) - symtab->reportDuplicate(leader, this); + if (leaderChunk->getSize() != getSection(sym)->SizeOfRawData) { + if (!config->mingw || leaderChunk->sectionDefLength != def->Length) + symtab->reportDuplicate(leader, this); + } break; case IMAGE_COMDAT_SELECT_EXACT_MATCH: { @@ -661,7 +667,7 @@ COMDATType selection = (COMDATType)def->Selection; if (leader->isCOMDAT) - handleComdatSelection(sym, selection, prevailing, leader); + handleComdatSelection(sym, selection, prevailing, leader, def); if (prevailing) { SectionChunk *c = readSection(sectionNumber, def, getName()); Index: lld/test/COFF/Inputs/comdat-binutils.yaml =================================================================== --- /dev/null +++ lld/test/COFF/Inputs/comdat-binutils.yaml @@ -0,0 +1,30 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ IMAGE_FILE_RELOCS_STRIPPED, IMAGE_FILE_LINE_NUMS_STRIPPED ] +sections: + - Name: '.rdata$mysymbol' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 2A000000000000000000000000000000 +symbols: + - Name: '.rdata$mysymbol' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + Selection: IMAGE_COMDAT_SELECT_SAME_SIZE + - Name: mysymbol + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... Index: lld/test/COFF/Inputs/comdat-llvm.yaml =================================================================== --- /dev/null +++ lld/test/COFF/Inputs/comdat-llvm.yaml @@ -0,0 +1,30 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.rdata$mysymbol' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] + Alignment: 1 + SectionData: 2A +symbols: + - Name: '.rdata$mysymbol' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3686517206 + Number: 1 + Selection: IMAGE_COMDAT_SELECT_SAME_SIZE + - Name: mysymbol + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... Index: lld/test/COFF/comdat-gcc-compatibility2.test =================================================================== --- /dev/null +++ lld/test/COFF/comdat-gcc-compatibility2.test @@ -0,0 +1,15 @@ +# RUN: yaml2obj %p/Inputs/comdat-llvm.yaml > %t.llvm.o +# RUN: yaml2obj %p/Inputs/comdat-binutils.yaml > %t.binutils.o +# RUN: lld-link -lldmingw -noentry -dll %t.llvm.o %t.binutils.o -out:%t.dll +# RUN: lld-link -lldmingw -noentry -dll %t.binutils.o %t.llvm.o -out:%t.dll +# RUN: not lld-link -noentry -dll %t.llvm.o %t.binutils.o -out:%t.dll +# RUN: not lld-link -noentry -dll %t.binutils.o %t.llvm.o -out:%t.dll + +# The test object files have been generated by assembling the following +# snippet using binutils and llvm. + +# .section .rdata$mysymbol, "dr" +# .linkonce same_size +# .globl mysymbol +#mysymbol: +# .byte 42