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 @@ -476,8 +476,23 @@ return symtab->addUndefined(name, this, sym.isWeakExternal()); } -void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection, - bool &prevailing, DefinedRegular *leader) { +static const coff_aux_section_definition *findSectionDef(COFFObjectFile *obj, + int32_t section) { + uint32_t numSymbols = obj->getNumberOfSymbols(); + for (uint32_t i = 0; i < numSymbols; ++i) { + COFFSymbolRef sym = check(obj->getSymbol(i)); + if (sym.getSectionNumber() != section) + continue; + if (const coff_aux_section_definition *def = sym.getSectionDefinition()) + return def; + } + return nullptr; +} + +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 +559,16 @@ 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) { + symtab->reportDuplicate(leader, this); + } else { + const coff_aux_section_definition *leaderDef = findSectionDef( + leaderChunk->file->getCOFFObj(), leaderChunk->getSectionNumber()); + if (!leaderDef || leaderDef->Length != def->Length) + symtab->reportDuplicate(leader, this); + } + } break; case IMAGE_COMDAT_SELECT_EXACT_MATCH: { @@ -661,7 +684,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