diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -291,14 +291,31 @@ // GOT, which means that the ifunc must be available when the main partition is // loaded) and TLS symbols (because we only know how to correctly process TLS // relocations for the main partition). +// +// We also need to move sections whose names are C identifiers that are referred +// to from __start_/__stop_ symbols because there will only be one set of +// symbols for the whole program. template void MarkLive::moveToMain() { - for (InputFile *file : objectFiles) - for (Symbol *s : file->getSymbols()) + StringSet<> startStopSymbolNames; + for (InputFile *file : objectFiles) { + for (Symbol *s : file->getSymbols()) { if (auto *d = dyn_cast(s)) if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section && d->section->isLive()) markSymbol(s); + StringRef name = s->getName(); + if (name.startswith("__start_")) + startStopSymbolNames.insert(name.substr(8)); + else if (name.startswith("__stop_")) + startStopSymbolNames.insert(name.substr(7)); + } + } + + for (InputSectionBase *sec : inputSections) + if (sec->isLive() && startStopSymbolNames.count(sec->name)) + enqueue(sec, 0); + mark(); } diff --git a/lld/test/ELF/partition-move-to-main-startstop.s b/lld/test/ELF/partition-move-to-main-startstop.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/partition-move-to-main-startstop.s @@ -0,0 +1,45 @@ +// REQUIRES: x86 +// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux +// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections +// RUN: llvm-readelf -S %t | FileCheck %s + +// We can't let the has_startstop section be split by partition because it is +// referenced by __start_ and __stop_ symbols, so the split could result in +// some sections being moved out of the __start_/__stop_ range. Make sure that +// that didn't happen by checking that there is only one section. +// +// It's fine for us to split no_startstop because of the lack of +// __start_/__stop_ symbols. + +// CHECK: has_startstop +// CHECK: no_startstop + +// CHECK-NOT: has_startstop +// CHECK: no_startstop +// CHECK-NOT: has_startstop + +.section .llvm_sympart.f1,"",@llvm_sympart +.asciz "part1" +.quad f1 + +.section .text._start,"ax",@progbits +.globl _start +_start: +call __start_has_startstop +call __stop_has_startstop + +.section .text.f1,"ax",@progbits +.globl f1 +f1: + +.section has_startstop,"ao",@progbits,.text._start,unique,1 +.quad 1 + +.section has_startstop,"ao",@progbits,.text.f1,unique,2 +.quad 2 + +.section no_startstop,"ao",@progbits,.text._start,unique,1 +.quad 3 + +.section no_startstop,"ao",@progbits,.text.f1,unique,2 +.quad 4