diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -270,7 +270,7 @@ if (isReserved(sec) || script->shouldKeep(sec)) { enqueue(sec, 0); - } else if (isValidCIdentifier(sec->name)) { + } else if (isValidCIdentifier(sec->name) && !sec->nextInSectionGroup) { cNamedSections[saver.save("__start_" + sec->name)].push_back(sec); cNamedSections[saver.save("__stop_" + sec->name)].push_back(sec); } diff --git a/lld/test/ELF/gc-sections-startstop.s b/lld/test/ELF/gc-sections-startstop.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/gc-sections-startstop.s @@ -0,0 +1,47 @@ +## Check that group members are retained or discarded as a unit, and +## sections whose names are C identifiers aren't considered roots if +## they're members of a group. + +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld %t.o --gc-sections -o %t +# RUN: llvm-readelf -s %t | FileCheck %s + +# RUN: echo ".global __start___data; __start___data:" > %t2.s +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t2.so +# RUN: ld.lld %t.o --gc-sections -o %t2 %t2.so +# RUN: llvm-readelf -s %t2 | FileCheck %s + +# CHECK: [[#%x,ADDR:]] {{.*}} __start___data +# CHECK: [[#ADDR + 8]] {{.*}} __stop___data +# CHECK: _start +# CHECK: f +# CHECK-NOT: g + +.weak __start___data +.weak __stop___data + +.section .text,"ax",@progbits +.global _start +_start: + .quad __start___data - . + .quad __stop___data - . + call f + +.section __data,"axG",@progbits,f +.quad 0 + +.section .text.f,"axG",@progbits,f +.global f +f: + nop + +.section __data,"axG",@progbits,g +.quad 0 + +.section .text.g,"axG",@progbits,g +.global g +g: + nop diff --git a/lld/test/ELF/startstop-gccollect.s b/lld/test/ELF/startstop-gccollect.s deleted file mode 100644 --- a/lld/test/ELF/startstop-gccollect.s +++ /dev/null @@ -1,44 +0,0 @@ -# REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t - -## Default run: sections foo and bar exist in output -# RUN: ld.lld %t -o %tout -# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s - -## Check that foo and bar sections are not garbage collected, -## we do not want to reclaim sections if they are referred -## by __start_* and __stop_* symbols. -# RUN: ld.lld %t --gc-sections -o %tout -# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s - -# RUN: echo ".global __start_foo; __start_foo:" > %t2.s -# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o -# RUN: ld.lld -shared %t2.o -o %t2.so -# RUN: ld.lld %t --gc-sections -o %tout %t2.so -# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s - -# DISASM: <_start>: -# DISASM-NEXT: callq {{.*}} <__start_foo> -# DISASM-NEXT: callq {{.*}} <__stop_bar> -# DISASM-EMPTY: -# DISASM-NEXT: Disassembly of section foo: -# DISASM-EMPTY: -# DISASM-NEXT: <__start_foo>: -# DISASM-NEXT: nop -# DISASM-EMPTY: -# DISASM-NEXT: Disassembly of section bar: -# DISASM-EMPTY: -# DISASM-NEXT: : -# DISASM-NEXT: nop - -.global _start -.text -_start: - callq __start_foo - callq __stop_bar - -.section foo,"ax" - nop - -.section bar,"ax" - nop