Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ struct Config {
bool optRemarksWithHotness;
bool picThunk;
bool pie;
bool printGcSections;
llvm::StringRef printGcSections;
bool printIcfSections;
bool printMemoryUsage;
std::optional<uint64_t> randomizeSectionPadding;
Expand Down
10 changes: 8 additions & 2 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1510,8 +1510,14 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
ctx.arg.pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
ctx.arg.printIcfSections =
args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);
ctx.arg.printGcSections =
args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
if (auto *arg =
args.getLastArg(OPT_print_gc_sections, OPT_no_print_gc_sections,
OPT_print_gc_sections_eq)) {
if (arg->getOption().matches(OPT_print_gc_sections))
ctx.arg.printGcSections = "-";
else if (arg->getOption().matches(OPT_print_gc_sections_eq))
ctx.arg.printGcSections = arg->getValue();
}
ctx.arg.printMemoryUsage = args.hasArg(OPT_print_memory_usage);
ctx.arg.printArchiveStats = args.getLastArgValue(OPT_print_archive_stats);
ctx.arg.printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order);
Expand Down
16 changes: 12 additions & 4 deletions lld/ELF/MarkLive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,10 +528,18 @@ template <class ELFT> void elf::markLive(Ctx &ctx) {
MarkLive<ELFT, false>(ctx, 1).moveToMain();

// Report garbage-collected sections.
if (ctx.arg.printGcSections)
for (InputSectionBase *sec : ctx.inputSections)
if (!sec->isLive())
Msg(ctx) << "removing unused section " << sec;
if (ctx.arg.printGcSections.empty())
return;
std::error_code ec;
raw_fd_ostream os = ctx.openAuxiliaryFile(ctx.arg.printGcSections, ec);
if (ec) {
Err(ctx) << "cannot open --print-gc-sections= file "
<< ctx.arg.printGcSections << ": " << ec.message();
return;
}
for (InputSectionBase *sec : ctx.inputSections)
if (!sec->isLive())
os << "removing unused section " << toStr(ctx, sec) << '\n';
}

template void elf::markLive<ELF32LE>(Ctx &);
Expand Down
3 changes: 3 additions & 0 deletions lld/ELF/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ defm pie: B<"pie",
defm print_gc_sections: B<"print-gc-sections",
"List removed unused sections",
"Do not list removed unused sections (default)">;
def print_gc_sections_eq: JJ<"print-gc-sections=">,
HelpText<"List removed unused sections to <file>">,
MetaVarName<"<file>">;

defm print_icf_sections: B<"print-icf-sections",
"List identical folded sections",
Expand Down
3 changes: 3 additions & 0 deletions lld/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ Non-comprehensive list of changes in this release
ELF Improvements
----------------

* ``--print-gc-sections=<file>`` prints garbage collection section listing to a file.
(`#159706 <https://github.com/llvm/llvm-project/pull/159706>`_)

Breaking changes
----------------

Expand Down
2 changes: 2 additions & 0 deletions lld/docs/ld.lld.1
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ Don't use.

.It Fl -print-gc-sections
List removed unused sections.
.It Fl -print-gc-sections Ns = Ns Ar file
List removed unused sections to the specified file.
.It Fl -print-icf-sections
List identical folded sections.
.It Fl -print-map
Expand Down
11 changes: 10 additions & 1 deletion lld/test/ELF/gc-sections-print.s
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
# RUN: ld.lld %t --gc-sections --print-gc-sections -o %t2 2>&1 | FileCheck -check-prefix=PRINT %s
# RUN: ld.lld %t --gc-sections --print-gc-sections=- -o %t2 2>&1 | FileCheck -check-prefix=PRINT %s
# RUN: ld.lld %t --gc-sections --print-gc-sections=%t.txt
# RUN: FileCheck --check-prefix=PRINT %s --input-file=%t.txt

# PRINT: removing unused section {{.*}}:(.text.x)
# PRINT-NEXT: removing unused section {{.*}}:(.text.y)

# RUN: ld.lld %t --gc-sections --print-gc-sections --no-print-gc-sections -o %t2 >& %t.log
# RUN: rm %t.txt
# RUN: ld.lld %t --gc-sections --print-gc-sections --print-gc-sections=%t.txt --no-print-gc-sections -o %t2 >& %t.log
# RUN: not ls %t.txt
# RUN: echo >> %t.log
# RUN: FileCheck -check-prefix=NOPRINT %s < %t.log

# NOPRINT-NOT: removing

# RUN: not ld.lld %t --gc-sections --print-gc-sections=/ -o %t2 2>&1 | FileCheck --check-prefix=ERR %s

# ERR: error: cannot open --print-gc-sections= file /: {{.*}}

.globl _start
.protected a, x, y
_start:
Expand Down