diff options
| -rw-r--r-- | lld/ELF/MarkLive.cpp | 23 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/sections-gc2.s | 37 | ||||
| -rw-r--r-- | lld/test/ELF/startstop-gccollect.s | 16 |
3 files changed, 61 insertions, 15 deletions
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 8f75de6dc30..9528708b584 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -170,12 +170,7 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) { if (!(Sec->Flags & SHF_ALLOC)) return true; - // We do not want to reclaim sections if they can be referred - // by __start_* and __stop_* symbols. StringRef S = Sec->Name; - if (isValidCIdentifier(S)) - return true; - return S.startswith(".ctors") || S.startswith(".dtors") || S.startswith(".init") || S.startswith(".fini") || S.startswith(".jcr"); @@ -226,11 +221,22 @@ template <class ELFT> void elf::markLive() { for (StringRef S : Config->Undefined) MarkSymbol(Symtab<ELFT>::X->find(S)); + // Remember which __start_* or __stop_* symbols are used so that we don't gc + // those sections. + DenseSet<StringRef> UsedStartStopNames; + // Preserve externally-visible symbols if the symbols defined by this // file can interrupt other ELF file's symbols at runtime. - for (const Symbol *S : Symtab<ELFT>::X->getSymbols()) - if (S->includeInDynsym()) + for (const Symbol *S : Symtab<ELFT>::X->getSymbols()) { + if (auto *U = dyn_cast_or_null<Undefined>(S->body())) { + StringRef Name = U->getName(); + for (StringRef Prefix : {"__start_", "__stop_"}) + if (Name.startswith(Prefix)) + UsedStartStopNames.insert(Name.substr(Prefix.size())); + } else if (S->includeInDynsym()) { MarkSymbol(S->body()); + } + } // Preserve special sections and those which are specified in linker // script KEEP command. @@ -240,7 +246,8 @@ template <class ELFT> void elf::markLive() { // referred by .eh_frame here. if (auto *EH = dyn_cast_or_null<EhInputSection<ELFT>>(Sec)) scanEhFrameSection<ELFT>(*EH, Enqueue); - if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec)) + if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec) || + UsedStartStopNames.count(Sec->Name)) Enqueue({Sec, 0}); } diff --git a/lld/test/ELF/linkerscript/sections-gc2.s b/lld/test/ELF/linkerscript/sections-gc2.s new file mode 100644 index 00000000000..675fe3901c0 --- /dev/null +++ b/lld/test/ELF/linkerscript/sections-gc2.s @@ -0,0 +1,37 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { \ +# RUN: used_in_reloc : { *(used_in_reloc) } \ +# RUN: used_in_script : { *(used_in_script) } \ +# RUN: .data : { *(.data) } \ +# RUN: }" > %t.script +# RUN: ld.lld -T %t.script -o %t.so %t.o -shared --gc-sections +# RUN: llvm-objdump -h %t.so | FileCheck %s + +# CHECK: Idx Name Size Address Type +# CHECK-NEXT: 0 +# CHECK-NEXT: used_in_reloc +# CHECK-NEXT: .dynsym +# CHECK-NEXT: .hash +# CHECK-NEXT: .dynstr +# CHECK-NEXT: .rela.dyn +# CHECK-NEXT: .data +# CHECK-NEXT: .dynamic +# CHECK-NEXT: .comment +# CHECK-NEXT: .symtab +# CHECK-NEXT: .shstrtab +# CHECK-NEXT: .strtab + + .data + .global foo +foo: + .quad __start_used_in_reloc + + .section unused,"a" + .quad 0 + + .section used_in_script,"a" + .quad 0 + + .section used_in_reloc,"a" + .quad 0 diff --git a/lld/test/ELF/startstop-gccollect.s b/lld/test/ELF/startstop-gccollect.s index 589ccafafcc..daff08187cd 100644 --- a/lld/test/ELF/startstop-gccollect.s +++ b/lld/test/ELF/startstop-gccollect.s @@ -6,24 +6,26 @@ # 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 can be referred +## 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 # DISASM: _start: -# DISASM-NEXT: 201000: 90 nop +# DISASM-NEXT: 201000: e8 05 00 00 00 callq 5 <__start_foo> +# DISASM-NEXT: 201005: e8 01 00 00 00 callq 1 <__start_bar> # DISASM-NEXT: Disassembly of section foo: -# DISASM-NEXT: foo: -# DISASM-NEXT: 201001: 90 nop +# DISASM-NEXT: __start_foo: +# DISASM-NEXT: 20100a: 90 nop # DISASM-NEXT: Disassembly of section bar: -# DISASM-NEXT: bar: -# DISASM-NEXT: 201002: 90 nop +# DISASM-NEXT: __start_bar: +# DISASM-NEXT: 20100b: 90 nop .global _start .text _start: - nop + callq __start_foo + callq __start_bar .section foo,"ax" nop |

