diff --git a/src/cmdline.cc b/src/cmdline.cc index 1ee5af87d9..cbbf2005c4 100644 --- a/src/cmdline.cc +++ b/src/cmdline.cc @@ -92,6 +92,8 @@ static const char helpmsg[] = R"( --no-demangle --detach Create separate debug info file in the background (default) --no-detach + --discard-section SECTION Discard an input section + --no-discard-section SECTION --enable-new-dtags Emit DT_RUNPATH for --rpath (default) --disable-new-dtags Emit DT_RPATH for --rpath --execute-only Make executable segments unreadable @@ -1128,6 +1130,10 @@ std::vector parse_nonpositional_args(Context &ctx) { ctx.arg.print_gc_sections = true; } else if (read_flag("no-print-gc-sections")) { ctx.arg.print_gc_sections = false; + } else if (read_arg("discard-section")) { + ctx.arg.discard_section.insert(arg); + } else if (read_arg("no-discard-section")) { + ctx.arg.discard_section.erase(arg); } else if (read_arg("icf")) { if (arg == "all") { ctx.arg.icf = true; diff --git a/src/input-files.cc b/src/input-files.cc index 3170221da6..55d6212eef 100644 --- a/src/input-files.cc +++ b/src/input-files.cc @@ -353,6 +353,10 @@ void ObjectFile::initialize_sections(Context &ctx) { is_debug_section(shdr, name)) continue; + // Ignore section is specified by --discard-section. + if (ctx.arg.discard_section.contains(name)) + continue; + if (name == ".comment" && this->get_string(ctx, shdr).starts_with("rustc ")) this->is_rust_obj = true; diff --git a/src/mold.h b/src/mold.h index c667479ae8..9cb32ad2a9 100644 --- a/src/mold.h +++ b/src/mold.h @@ -2049,6 +2049,7 @@ struct Context { std::optional *>> retain_symbols_file; std::unordered_map section_align; std::unordered_map section_start; + std::unordered_set discard_section; std::unordered_set ignore_ir_file; std::unordered_set wrap; std::vector section_order; diff --git a/test/discard-section.s b/test/discard-section.s new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/discard-section.sh b/test/discard-section.sh new file mode 100755 index 0000000000..8ae0984e98 --- /dev/null +++ b/test/discard-section.sh @@ -0,0 +1,25 @@ +#!/bin/bash +. $(dirname $0)/common.inc + +cat <<'EOF' | $CC -x assembler -c -o $t/a.o -x assembler - + +.section .foo,"a" +.ascii "foo\0" +.section .bar,"a" +.ascii "bar\0" +.section .text +.globl _start +_start: +EOF + +./mold -o $t/exe0 $t/a.o +readelf -S $t/exe0 | grep '.foo' +readelf -S $t/exe0 | grep '.bar' + +./mold -o $t/exe1 $t/a.o --discard-section='.foo' +readelf -S $t/exe1 | grep -v '.foo' +readelf -S $t/exe1 | grep '.bar' + +./mold -o $t/exe2 $t/a.o --discard-section='foo' --discard-section='boo' --no-discard-section='foo' +readelf -S $t/exe2 | grep '.foo' +readelf -S $t/exe2 | grep -v '.bar' diff --git a/test/out/test/x86_64/repro/exe b/test/out/test/x86_64/repro/exe new file mode 100755 index 0000000000..5c05838426 Binary files /dev/null and b/test/out/test/x86_64/repro/exe differ