https://github.com/c-rhodes updated https://github.com/llvm/llvm-project/pull/177306
>From c8122e4004d2b7a9a286f4c07b3928aadb915423 Mon Sep 17 00:00:00 2001 From: Fangrui Song <[email protected]> Date: Wed, 21 Jan 2026 18:58:35 -0800 Subject: [PATCH] [ELF] --why-live: Skip symbol at index 0 and section symbols, handle .eh_frame symbols (#177099) Symbols of empty names can be matched by `--why-live='*'`, which are generally not useful. * The first entry in a symbol table (STB_LOCAL and undefined) * `STT_SECTION` symbols (emitted by LLVM integrated assembler when needed by relocations). These input section symbols will be demoted by `demoteAndCopyLocalSymbols`, so technically not really live. In addition, such symbols of non-allocable sections currently lead to crashes: `whyLive` does not record the section, causing the second iteration of the `while (true)` loop in printWhyLive to call `std::get<Symbol *>(cur)` when `cur` is an `InputSectionBase *`. In addition, handle GCC crtendS.o `__FRAME_END__`, which is defined relative to a `.eh_frame` section created with `__attribute__((used, section(".eh_frame")))`. Fix #176890 (cherry picked from commit 1869b15a0569e4e0fa0b97ee462db4e826519d4f) --- lld/ELF/MarkLive.cpp | 9 +++++++- lld/test/ELF/why-live.test | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index a7b0f08c8d954..c43022a6b9d3f 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -202,6 +202,9 @@ void MarkLive<ELFT, TrackWhyLive>::resolveReloc(InputSectionBase &sec, // LSDAs and personality functions if we found that they were unused. template <class ELFT, bool TrackWhyLive> void MarkLive<ELFT, TrackWhyLive>::scanEhFrameSection(EhInputSection &eh) { + if (TrackWhyLive) + whyLive.try_emplace(&eh, + LiveReason{std::nullopt, "exception handling frame"}); ArrayRef<Relocation> rels = eh.rels; for (const EhSectionPiece &cie : eh.cies) if (cie.firstRelocation != unsigned(-1)) @@ -443,9 +446,13 @@ void MarkLive<ELFT, TrackWhyLive>::run() { for (Symbol *sym : ctx.symtab->getSymbols()) handleSym(sym); + // Handle local symbols, skipping the symbol at index 0 and section + // symbols, which usually have empty names and technically not live. Note: + // a live section may lack an associated section symbol, making them + // unreliable liveness indicators. for (ELFFileBase *file : ctx.objectFiles) for (Symbol *sym : file->getSymbols()) - if (sym->isLocal()) + if (sym->isLocal() && sym->isDefined() && !sym->isSection()) handleSym(sym); } } diff --git a/lld/test/ELF/why-live.test b/lld/test/ELF/why-live.test index d8f8cc7b6db64..a281f9942985e 100644 --- a/lld/test/ELF/why-live.test +++ b/lld/test/ELF/why-live.test @@ -4,6 +4,7 @@ # RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o shared.o shared.s # RUN: ld.lld -shared shared.o -o a.so # RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o a.o a.s +# RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o b.o b.s #--- shared.s .globl test_shared @@ -159,3 +160,46 @@ test_local: # MULTIPLE-DAG: live symbol: a.o:(test_section_offset) # MULTIPLE-DAG: live symbol: a.o:(test_section_offset_within_symbol) # MULTIPLE-NOT: live symbol + +#--- b.s +## --why-live='*' skips symbol at index 0 and section symbols. +# RUN: ld.lld b.o --threads=1 --gc-sections --why-live="*" | FileCheck %s --check-prefix=STAR --match-full-lines +# STAR-NOT: {{.}} +# STAR: live symbol: b.o:(_start) (entry point) +# STAR-NEXT: live symbol: b.o:(b.s) (no section) +# STAR-NEXT: live symbol: b.o:(str1) +# STAR-NEXT: >>> referenced by: b.o:(.alloc) +# STAR-NEXT: >>> referenced by: b.o:(.text) +# STAR-NEXT: >>> contained live symbol: b.o:(_start) (entry point) +# STAR-NEXT: live symbol: b.o:(note1) +# STAR-NEXT: >>> in live section: b.o:(.note.1) (reserved) +# STAR-NEXT: live symbol: b.o:(__FRAME_END__) +# STAR-NEXT: >>> in live section: b.o:(.eh_frame) (exception handling frame) +# STAR-NOT: {{.}} + +## STT_FILE symbol +.file "b.s" + +.text +.globl _start +_start: + call .alloc + +.section .alloc,"a" + lea str1(%rip), %rax + +.section .nonalloc + .long .nonalloc + +.section .note.1,"a",@note +note1: + +## GCC crtendS.o has such a local symbol relative to an explicit .eh_frame +## section. +.section .eh_frame,"a" +__FRAME_END__: + .long 0 + +.section .rodata.str1.1,"aMS",@progbits,1 +str1: + .asciz "str1" _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
