Index: lld/trunk/COFF/InputFiles.cpp =================================================================== --- lld/trunk/COFF/InputFiles.cpp +++ lld/trunk/COFF/InputFiles.cpp @@ -223,14 +223,23 @@ void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym, const coff_aux_section_definition *Def, - uint32_t ParentSection) { - SectionChunk *Parent = SparseChunks[ParentSection]; + uint32_t ParentIndex) { + SectionChunk *Parent = SparseChunks[ParentIndex]; - // If the parent is pending, it probably means that its section definition - // appears after us in the symbol table. Leave the associated section as - // pending; we will handle it during the second pass in initializeSymbols(). - if (Parent == PendingComdat) + if (Parent == PendingComdat) { + // This can happen if an associative comdat refers to another associative + // comdat that appears after it (invalid per COFF spec) or to a section + // without any symbols. + StringRef Name, ParentName; + COFFObj->getSymbolName(Sym, Name); + + const coff_section *ParentSec; + COFFObj->getSection(ParentIndex, ParentSec); + COFFObj->getSectionName(ParentSec, ParentName); + error(toString(this) + ": associative comdat " + Name + + " has invalid reference to section " + ParentName); return; + } // Check whether the parent is prevailing. If it is, so are we, and we read // the section; otherwise mark it as discarded. @@ -326,8 +335,7 @@ // was pending at the point when the symbol was read. This can happen in // two cases: // 1) section definition symbol for a comdat leader; - // 2) symbol belongs to a comdat section associated with a section whose - // section definition symbol appears later in the symbol table. + // 2) symbol belongs to a comdat section associated with another section. // In both of these cases, we can expect the section to be resolved by // the time we finish visiting the remaining symbols in the symbol // table. So we postpone the handling of this symbol until that time. @@ -437,21 +445,15 @@ return Leader; } - // Read associative section definitions and prepare to handle the comdat - // leader symbol by setting the section's ComdatDefs pointer if we encounter a - // non-associative comdat. + // Prepare to handle the comdat leader symbol by setting the section's + // ComdatDefs pointer if we encounter a non-associative comdat. if (SparseChunks[SectionNumber] == PendingComdat) { if (const coff_aux_section_definition *Def = Sym.getSectionDefinition()) { - if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) - readAssociativeDefinition(Sym, Def); - else + if (Def->Selection != IMAGE_COMDAT_SELECT_ASSOCIATIVE) ComdatDefs[SectionNumber] = Def; } - } - - // readAssociativeDefinition() writes to SparseChunks, so need to check again. - if (SparseChunks[SectionNumber] == PendingComdat) return None; + } return createRegular(Sym); } Index: lld/trunk/test/COFF/associative-comdat-empty.s =================================================================== --- lld/trunk/test/COFF/associative-comdat-empty.s +++ lld/trunk/test/COFF/associative-comdat-empty.s @@ -0,0 +1,56 @@ +# RUN: yaml2obj < %s > %t.obj +# RUN: not lld-link /include:symbol /dll /noentry /nodefaultlib %t.obj /out:%t.exe 2>&1 | FileCheck %s + +# Tests an associative comdat being associated with an empty section errors. +# CHECK: lld-link: error: {{.*}}: associative comdat .text$ac1 has invalid reference to section .text$nm +# CHECK-NOT: lld-link: error: + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.text$ac1' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 1 + SectionData: '01000000' + - Name: '.text$nm' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 1 + SectionData: '01000000' +symbols: + - Name: '.text$ac1' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3099354981 + Number: 2 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: '.text$nm' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3099354981 + Number: 4 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: assocsym + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC +... + + Index: lld/trunk/test/COFF/associative-comdat-order.s =================================================================== --- lld/trunk/test/COFF/associative-comdat-order.s +++ lld/trunk/test/COFF/associative-comdat-order.s @@ -0,0 +1,85 @@ +# RUN: yaml2obj < %s > %t.obj +# RUN: not lld-link /include:symbol /dll /noentry /nodefaultlib %t.obj /out:%t.exe 2>&1 | FileCheck %s + +# Tests that an associative comdat being associated with another +# associated comdat later in the file produces an error. +# CHECK: lld-link: error: {{.*}}: associative comdat .text$ac1 has invalid reference to section .text$ac2 +# CHECK-NOT: lld-link: error: + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.text$ac1' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 1 + SectionData: '01000000' + - Name: '.text$ac2' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 1 + SectionData: '01000000' + - Name: '.text$nm' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 1 + SectionData: '01000000' +symbols: + - Name: '.text$ac1' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3099354981 + Number: 2 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: '.text$ac2' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3099354981 + Number: 3 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: '.text$nm' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3099354981 + Number: 4 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: symbol + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: assocsym2 + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: assocsym + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC +... +