diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 3401c016dbe9..2daee212cc00 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1133,7 +1133,7 @@ static void readConfigs(opt::InputArgList &args) { config->zShstk = hasZOption(args, "shstk"); config->zStackSize = args::getZOptionValue(args, OPT_z, "stack-size", 0); config->zStartStopGC = - getZFlag(args, "start-stop-gc", "nostart-stop-gc", false); + getZFlag(args, "start-stop-gc", "nostart-stop-gc", true); config->zStartStopVisibility = getZStartStopVisibility(args); config->zText = getZFlag(args, "text", "notext", true); config->zWxneeded = hasZOption(args, "wxneeded"); diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index a384a4250b27..e828429b421c 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -270,8 +270,11 @@ template void MarkLive::run() { if (isReserved(sec) || script->shouldKeep(sec)) { enqueue(sec, 0); - } else if (!config->zStartStopGC && isValidCIdentifier(sec->name) && - !sec->nextInSectionGroup) { + } else if ((!config->zStartStopGC || sec->name.startswith("__libc_")) && + isValidCIdentifier(sec->name)) { + // As a workaround for glibc libc.a before 2.34 + // (https://sourceware.org/PR27492), retain __libc_atexit and similar + // sections regardless of zStartStopGC. 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-metadata-startstop.s b/lld/test/ELF/gc-sections-metadata-startstop.s index 4f6553365c1d..76134525b4ce 100644 --- a/lld/test/ELF/gc-sections-metadata-startstop.s +++ b/lld/test/ELF/gc-sections-metadata-startstop.s @@ -2,13 +2,13 @@ # LINK_ORDER cnamed sections are not kept alive by the __start_* reference. # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -# RUN: ld.lld --gc-sections %t.o -o %t -# RUN: llvm-objdump --section-headers -t %t | FileCheck %s # RUN: ld.lld --gc-sections -z start-stop-gc -z nostart-stop-gc %t.o -o %t # RUN: llvm-objdump --section-headers -t %t | FileCheck %s -## With -z start-stop-gc, non-SHF_LINK_ORDER non-SHF_GROUP C identifier name +## With -z start-stop-gc (default), non-SHF_LINK_ORDER C identifier name ## sections are not retained by __start_/__stop_ references. +# RUN: ld.lld --gc-sections %t.o -o %t +# RUN: llvm-readelf -S -s %t | FileCheck %s --check-prefix=GC # RUN: ld.lld --gc-sections -z start-stop-gc %t.o -o %t1 # RUN: llvm-readelf -S -s %t1 | FileCheck %s --check-prefix=GC @@ -44,4 +44,3 @@ _start: .section yy,"ao",@progbits,.foo .quad 0 - diff --git a/lld/test/ELF/gc-sections-startstop.s b/lld/test/ELF/gc-sections-startstop.s index 20c244af6a93..569cd3cdd10f 100644 --- a/lld/test/ELF/gc-sections-startstop.s +++ b/lld/test/ELF/gc-sections-startstop.s @@ -1,6 +1,4 @@ -## 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. +## Check that group members are retained or discarded as a unit. # REQUIRES: x86 @@ -10,24 +8,40 @@ # 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 -shared %t2.o --soname=t2 -o %t2.so # RUN: ld.lld %t.o --gc-sections -o %t2 %t2.so # RUN: llvm-readelf -s %t2 | FileCheck %s +## The referenced __data is retained. # CHECK: [[#%x,ADDR:]] {{.*}} __start___data # CHECK: [[#ADDR + 8]] {{.*}} __stop___data +## __libc_atexit is retained even if there is no reference, as a workaround for +## glibc<2.34 (BZ #27492). +# CHECK: [[#%x,ADDR:]] {{.*}} __start___libc_atexit +# CHECK: [[#ADDR + 8]] {{.*}} __stop___libc_atexit # CHECK: _start # CHECK: f # CHECK-NOT: g +## If -z nostart-stop-gc, sections whose names are C identifiers are retained by +## __start_/__stop_ references. +# RUN: ld.lld %t.o %t2.so --gc-sections -z nostart-stop-gc -o %t3 +# RUN: llvm-readelf -s %t3 | FileCheck %s --check-prefix=NOGC +# NOGC: [[#%x,ADDR:]] {{.*}} __start___data +# NOGC: [[#ADDR + 16]] {{.*}} __stop___data + .weak __start___data .weak __stop___data +.weak __start___libc_atexit +.weak __stop___libc_atexit .section .text,"ax",@progbits .global _start _start: .quad __start___data - . .quad __stop___data - . + .quad __start___libc_atexit - . + .quad __stop___libc_atexit - . call f .section __data,"axG",@progbits,f @@ -45,3 +59,6 @@ f: .global g g: nop + +.section __libc_atexit,"a",@progbits +.quad 0 diff --git a/lld/test/ELF/linkerscript/sections-gc2.s b/lld/test/ELF/linkerscript/sections-gc2.s index 7b1fa8dacaf3..76be65fbdb4e 100644 --- a/lld/test/ELF/linkerscript/sections-gc2.s +++ b/lld/test/ELF/linkerscript/sections-gc2.s @@ -5,7 +5,7 @@ # RUN: used_in_script : { *(used_in_script) } \ # RUN: .text : { *(.text) } \ # RUN: }" > %t.script -# RUN: ld.lld -T %t.script -o %t.so %t.o --gc-sections +# RUN: ld.lld -T %t.script -o %t.so %t.o --gc-sections -z nostart-stop-gc # RUN: llvm-objdump -h %t.so | FileCheck %s # CHECK: Idx Name Size VMA Type diff --git a/lld/test/ELF/lto/section-name.ll b/lld/test/ELF/lto/section-name.ll index ac744926db6c..626c76609e18 100644 --- a/lld/test/ELF/lto/section-name.ll +++ b/lld/test/ELF/lto/section-name.ll @@ -2,7 +2,7 @@ ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld %t.o -o %t.so -shared ; RUN: llvm-readelf -S %t.so | FileCheck %s -; RUN: ld.lld %t.o -o %t.so -shared --gc-sections +; RUN: ld.lld %t.o -o %t.so -shared --gc-sections -z nostart-stop-gc ; RUN: llvm-readelf -S %t.so | FileCheck --check-prefix=GC %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/lld/test/ELF/relocatable-gc.s b/lld/test/ELF/relocatable-gc.s index a59aa10b4cd6..7d367ba57ec4 100644 --- a/lld/test/ELF/relocatable-gc.s +++ b/lld/test/ELF/relocatable-gc.s @@ -42,7 +42,7 @@ ## If .text is retained, its referenced qux and .fred are retained as well. ## fred_und is used (by .fred) and thus emitted. ## Note, GNU ld does not retain qux. -# RUN: ld.lld -r --gc-sections -e _start %t.o -o %tstart.ro +# RUN: ld.lld -r --gc-sections -z nostart-stop-gc -e _start %t.o -o %tstart.ro # RUN: llvm-readelf -Ss %tstart.ro | FileCheck %s --check-prefix=KEEP_START # KEEP_START: [ 1] .text