[lld] bfa4235 - [lld][ELF] Support for zero flag section groups

Petr Hosek via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 16 14:33:51 PST 2021


Author: Petr Hosek
Date: 2021-02-16T14:33:09-08:00
New Revision: bfa4235e6e92ce2d3df486828ca2b6aef9705c07

URL: https://github.com/llvm/llvm-project/commit/bfa4235e6e92ce2d3df486828ca2b6aef9705c07
DIFF: https://github.com/llvm/llvm-project/commit/bfa4235e6e92ce2d3df486828ca2b6aef9705c07.diff

LOG: [lld][ELF] Support for zero flag section groups

This change introduces support for zero flag ELF section groups to lld.
lld already supports COMDAT sections, which in ELF are a special type of
ELF section groups. These are generally useful to enable linker GC where
you want a group of sections to always travel together, that is to be
either retained or discarded as a whole, but without the COMDAT
semantics. Other ELF linkers already support zero flag ELF section
groups and this change helps us reach feature parity.

Differential Revision: https://reviews.llvm.org/D96636

Added: 
    

Modified: 
    lld/ELF/InputFiles.cpp
    lld/test/ELF/gc-sections-group.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index aac7c5c42d4a..3de741d2a571 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -609,27 +609,20 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
       StringRef signature = getShtGroupSignature(objSections, sec);
       this->sections[i] = &InputSection::discarded;
 
-
       ArrayRef<Elf_Word> entries =
           CHECK(obj.template getSectionContentsAsArray<Elf_Word>(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 ||
+      bool keepGroup =
+          (flag & GRP_COMDAT) == 0 || ignoreComdats ||
           symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this)
               .second;
-      if (isNew) {
+      if (keepGroup) {
         if (config->relocatable)
           this->sections[i] = createInputSection(sec);
         selectedGroups.push_back(entries);

diff  --git a/lld/test/ELF/gc-sections-group.s b/lld/test/ELF/gc-sections-group.s
index 8f713f5cf1e4..da4cad98f365 100644
--- a/lld/test/ELF/gc-sections-group.s
+++ b/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.ccc is retained because it is not in a group.
+# CHECK-DEAD-NOT: Name: .myanote.aaa
+# CHECK-DEAD-NOT: Name: .mytext.aaa
+# CHECK-DEAD-NOT: Name: .mybss.aaa
+# CHECK-DEAD-NOT: Name: .mynote.aaa
+# CHECK-DEAD-NOT: Name: .myanote.bbb
+# CHECK-DEAD-NOT: Name: .mytext.bbb
+# CHECK-DEAD-NOT: Name: .mybss.bbb
+# CHECK-DEAD-NOT: Name: .mynote.bbb
+# CHECK-DEAD:     Name: .mynote.ccc
+
+# RUN: ld.lld --gc-sections %t.o -o %t -e anote_aaa
+# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-GROUP
+# RUN: ld.lld --gc-sections %t.o -o %t -e aaa
+# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-GROUP
+# RUN: ld.lld --gc-sections %t.o -o %t -e bss_aaa
+# 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_aaa
+# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-GROUP
+
+# CHECK-LIVE-GROUP: Name: .myanote.aaa
+# CHECK-LIVE-GROUP: Name: .mytext.aaa
+# CHECK-LIVE-GROUP: Name: .mybss.aaa
+# CHECK-LIVE-GROUP: Name: .mynote.aaa
+# CHECK-LIVE-GROUP-NOT: Name: .myanote.bbb
+# CHECK-LIVE-GROUP-NOT: Name: .mytext.bbb
+# CHECK-LIVE-GROUP-NOT: Name: .mybss.bbb
+# CHECK-LIVE-GROUP-NOT: Name: .mynote.bbb
+# CHECK-LIVE-GROUP: Name: .mynote.ccc
+
+# RUN: ld.lld --gc-sections %t.o -o %t -e anote_bbb
+# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT
+# RUN: ld.lld --gc-sections %t.o -o %t -e bbb
+# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT
+# RUN: ld.lld --gc-sections %t.o -o %t -e bss_bbb
+# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT
+
+## note_bbb 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_bbb
+# RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=CHECK-LIVE-COMDAT
+
+# CHECK-LIVE-COMDAT-NOT: Name: .myanote.aaa
+# CHECK-LIVE-COMDAT-NOT: Name: .mytext.aaa
+# CHECK-LIVE-COMDAT-NOT: Name: .mybss.aaa
+# CHECK-LIVE-COMDAT-NOT: Name: .mynote.aaa
+# CHECK-LIVE-COMDAT: Name: .myanote.bbb
+# CHECK-LIVE-COMDAT: Name: .mytext.bbb
+# CHECK-LIVE-COMDAT: Name: .mybss.bbb
+# CHECK-LIVE-COMDAT: Name: .mynote.bbb
+# CHECK-LIVE-COMDAT: Name: .mynote.ccc
+
+## These sections are in a zero flag group `aaa`.
+.globl anote_aaa, aaa, bss_aaa, note_aaa
 
-# 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.aaa,"aG", at note,aaa
+anote_aaa:
+.byte 0
+
+.section .mytext.aaa,"axG", at progbits,aaa
+aaa:
+.byte 0
+
+.section .mybss.aaa,"awG", at nobits,aaa
+bss_aaa:
+.byte 0
+
+.section .mynote.aaa,"G", at note,aaa
+note_aaa:
+.byte 0
 
-.globl anote_foo, foo, bss_foo, note_foo
+## These sections are in a COMDAT group `bbb`.
+.globl anote_bbb, bbb, bss_bbb, note_bbb
 
-.section .myanote.foo,"aG", at note,foo,comdat
-anote_foo:
+.section .myanote.bbb,"aG", at note,bbb,comdat
+anote_bbb:
 .byte 0
 
-.section .mytext.foo,"axG", at progbits,foo,comdat
-foo:
+.section .mytext.bbb,"axG", at progbits,bbb,comdat
+bbb:
 .byte 0
 
-.section .mybss.foo,"awG", at nobits,foo,comdat
-bss_foo:
+.section .mybss.bbb,"awG", at nobits,bbb,comdat
+bss_bbb:
 .byte 0
 
-.section .mynote.foo,"G", at note,foo,comdat
-note_foo:
+.section .mynote.bbb,"G", at note,bbb,comdat
+note_bbb:
 .byte 0
 
-.section .mynote.bar,"", at note
+## This section isn't in any group.
+.section .mynote.ccc,"", at note
 .byte 0


        


More information about the llvm-commits mailing list