Index: lld/ELF/InputFiles.cpp =================================================================== --- lld/ELF/InputFiles.cpp +++ lld/ELF/InputFiles.cpp @@ -609,24 +609,17 @@ StringRef signature = getShtGroupSignature(objSections, sec); this->sections[i] = &InputSection::discarded; - ArrayRef entries = CHECK(obj.template getSectionContentsAsArray(sec), this); if (entries.empty()) fatal(toString(this) + ": empty SHT_GROUP"); - // The first word of a SHT_GROUP section contains flags. Currently, - // the standard defines only "GRP_COMDAT" flag for the COMDAT group. - // An group with the empty flag doesn't define anything; such sections - // are just skipped. - if (entries[0] == 0) - continue; - - if (entries[0] != GRP_COMDAT) + Elf_Word flag = entries[0]; + if (flag && flag != GRP_COMDAT) fatal(toString(this) + ": unsupported SHT_GROUP format"); bool isNew = - ignoreComdats || + (flag & GRP_COMDAT) == 0 || ignoreComdats || symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this) .second; if (isNew) { Index: lld/test/ELF/gc-sections-group.s =================================================================== --- lld/test/ELF/gc-sections-group.s +++ lld/test/ELF/gc-sections-group.s @@ -7,48 +7,99 @@ # RUN: ld.lld --gc-sections %t.o -o %t.dead # RUN: llvm-readobj -S %t.dead | FileCheck %s --check-prefix=CHECK-DEAD -## .mynote.bar is retained because it is not in a group. -# CHECK-DEAD-NOT: Name: .myanote.foo -# CHECK-DEAD-NOT: Name: .mytext.foo -# CHECK-DEAD-NOT: Name: .mybss.foo -# CHECK-DEAD-NOT: Name: .mynote.foo -# CHECK-DEAD: Name: .mynote.bar - -# RUN: ld.lld --gc-sections %t.o -o %t -e anote_foo -# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE -# RUN: ld.lld --gc-sections %t.o -o %t -e foo -# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE -# RUN: ld.lld --gc-sections %t.o -o %t -e bss_foo -# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE - -## note_foo as the entry point does not make much sense because it is defined +## .mynote.none is retained because it is not in a group. +# CHECK-DEAD-NOT: Name: .myanote.cmdt +# CHECK-DEAD-NOT: Name: .mytext.cmdt +# CHECK-DEAD-NOT: Name: .mybss.cmdt +# CHECK-DEAD-NOT: Name: .mynote.cmdt +# CHECK-DEAD-NOT: Name: .myanote.grp +# CHECK-DEAD-NOT: Name: .mytext.grp +# CHECK-DEAD-NOT: Name: .mybss.grp +# CHECK-DEAD-NOT: Name: .mynote.grp +# CHECK-DEAD: Name: .mynote.none + +# RUN: ld.lld --gc-sections %t.o -o %t -e anote_cmdt +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT +# RUN: ld.lld --gc-sections %t.o -o %t -e cmdt +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT +# RUN: ld.lld --gc-sections %t.o -o %t -e bss_cmdt +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT + +## note_cmdt as the entry point does not make much sense because it is defined +## in a non-SHF_ALLOC section. This is just to demonstrate the behavior. +# RUN: ld.lld --gc-sections %t.o -o %t -e note_cmdt +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT + +# CHECK-LIVE-COMDAT: Name: .myanote.cmdt +# CHECK-LIVE-COMDAT: Name: .mytext.cmdt +# CHECK-LIVE-COMDAT: Name: .mybss.cmdt +# CHECK-LIVE-COMDAT: Name: .mynote.cmdt +# CHECK-LIVE-COMDAT-NOT: Name: .myanote.grp +# CHECK-LIVE-COMDAT-NOT: Name: .mytext.grp +# CHECK-LIVE-COMDAT-NOT: Name: .mybss.grp +# CHECK-LIVE-COMDAT-NOT: Name: .mynote.grp +# CHECK-LIVE-COMDAT: Name: .mynote.none + +# RUN: ld.lld --gc-sections %t.o -o %t -e anote_grp +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-GROUP +# RUN: ld.lld --gc-sections %t.o -o %t -e grp +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-GROUP +# RUN: ld.lld --gc-sections %t.o -o %t -e bss_grp +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-GROUP + +## note_zero as the entry point does not make much sense because it is defined ## in a non-SHF_ALLOC section. This is just to demonstrate the behavior. -# RUN: ld.lld --gc-sections %t.o -o %t -e note_foo -# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE +# RUN: ld.lld --gc-sections %t.o -o %t -e note_grp +# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-GROUP + +# CHECK-LIVE-GROUP-NOT: Name: .myanote.cmdt +# CHECK-LIVE-GROUP-NOT: Name: .mytext.cmdt +# CHECK-LIVE-GROUP-NOT: Name: .mybss.cmdt +# CHECK-LIVE-GROUP-NOT: Name: .mynote.cmdt +# CHECK-LIVE-GROUP: Name: .myanote.grp +# CHECK-LIVE-GROUP: Name: .mytext.grp +# CHECK-LIVE-GROUP: Name: .mybss.grp +# CHECK-LIVE-GROUP: Name: .mynote.grp +# CHECK-LIVE-GROUP: Name: .mynote.none + +## These seections are in a COMDAT group `cmdt`. +.globl anote_cmdt, cmdt, bss_cmdt, note_cmdt -# CHECK-LIVE: Name: .myanote.foo -# CHECK-LIVE: Name: .mytext.foo -# CHECK-LIVE: Name: .mybss.foo -# CHECK-LIVE: Name: .mynote.foo -# CHECK-LIVE: Name: .mynote.bar +.section .myanote.cmdt,"aG",@note,cmdt,comdat +anote_cmdt: +.byte 0 + +.section .mytext.cmdt,"axG",@progbits,cmdt,comdat +cmdt: +.byte 0 + +.section .mybss.cmdt,"awG",@nobits,cmdt,comdat +bss_cmdt: +.byte 0 + +.section .mynote.cmdt,"G",@note,cmdt,comdat +note_cmdt: +.byte 0 -.globl anote_foo, foo, bss_foo, note_foo +## These sections are in a zero flag group `grp`. +.globl anote_grp, grp, bss_grp, note_grp -.section .myanote.foo,"aG",@note,foo,comdat -anote_foo: +.section .myanote.grp,"aG",@note,grp +anote_grp: .byte 0 -.section .mytext.foo,"axG",@progbits,foo,comdat -foo: +.section .mytext.grp,"axG",@progbits,grp +grp: .byte 0 -.section .mybss.foo,"awG",@nobits,foo,comdat -bss_foo: +.section .mybss.grp,"awG",@nobits,grp +bss_grp: .byte 0 -.section .mynote.foo,"G",@note,foo,comdat -note_foo: +.section .mynote.grp,"G",@note,grp +note_grp: .byte 0 -.section .mynote.bar,"",@note +## This section isn't in any group. +.section .mynote.none,"",@note .byte 0