From f24b99750102eb32f717a9a4153a7cb14120220b Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sat, 5 Feb 2022 11:23:02 +0900 Subject: [PATCH] [ELF} Add --warn-once --- elf/arch-arm64.cc | 4 ++-- elf/arch-i386.cc | 4 ++-- elf/arch-riscv64.cc | 4 ++-- elf/arch-x86-64.cc | 4 ++-- elf/cmdline.cc | 3 +++ elf/input-files.cc | 2 +- elf/input-sections.cc | 13 +++++++++---- elf/mold.h | 8 +++++++- test/elf/warn-once.sh | 30 ++++++++++++++++++++++++++++++ 9 files changed, 58 insertions(+), 14 deletions(-) create mode 100755 test/elf/warn-once.sh diff --git a/elf/arch-arm64.cc b/elf/arch-arm64.cc index c294a2b40c..0e380c0a09 100644 --- a/elf/arch-arm64.cc +++ b/elf/arch-arm64.cc @@ -355,7 +355,7 @@ void InputSection::apply_reloc_nonalloc(Context &ctx, u8 *base) { u8 *loc = base + rel.r_offset; if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } @@ -400,7 +400,7 @@ void InputSection::scan_relocations(Context &ctx) { Symbol &sym = *file.symbols[rel.r_sym]; if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } diff --git a/elf/arch-i386.cc b/elf/arch-i386.cc index b3c0d305be..7d2f56818e 100644 --- a/elf/arch-i386.cc +++ b/elf/arch-i386.cc @@ -272,7 +272,7 @@ void InputSection::apply_reloc_nonalloc(Context &ctx, u8 *base) { u8 *loc = base + rel.r_offset; if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } @@ -369,7 +369,7 @@ void InputSection::scan_relocations(Context &ctx) { Symbol &sym = *file.symbols[rel.r_sym]; if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } diff --git a/elf/arch-riscv64.cc b/elf/arch-riscv64.cc index eb12ea2939..d8e297e07a 100644 --- a/elf/arch-riscv64.cc +++ b/elf/arch-riscv64.cc @@ -422,7 +422,7 @@ void InputSection::apply_reloc_nonalloc(Context &ctx, u8 *base) { u8 *loc = base + rel.r_offset; if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } @@ -544,7 +544,7 @@ void InputSection::scan_relocations(Context &ctx) { Symbol &sym = *file.symbols[rel.r_sym]; if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } diff --git a/elf/arch-x86-64.cc b/elf/arch-x86-64.cc index bd88d45d03..fccacce326 100644 --- a/elf/arch-x86-64.cc +++ b/elf/arch-x86-64.cc @@ -481,7 +481,7 @@ void InputSection::apply_reloc_nonalloc(Context &ctx, u8 *base) { u8 *loc = base + rel.r_offset; if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } @@ -580,7 +580,7 @@ void InputSection::scan_relocations(Context &ctx) { u8 *loc = (u8 *)(contents.data() + rel.r_offset); if (!sym.file) { - report_undef(ctx, sym); + report_undef(ctx, file, sym); continue; } diff --git a/elf/cmdline.cc b/elf/cmdline.cc index 1f85302ca0..74c17cbb5a 100644 --- a/elf/cmdline.cc +++ b/elf/cmdline.cc @@ -132,6 +132,7 @@ static const char helpmsg[] = R"( --version-script FILE Read version script --warn-common Warn about common symbols --no-warn-common + --warn-once Only warn once for each undefined symbol --warn-unresolved-symbols Report unresolved symbols as warnings --error-unresolved-symbols Report unresolved symbols as errors (default) @@ -584,6 +585,8 @@ void parse_nonpositional_args(Context &ctx, ctx.arg.warn_common = true; } else if (read_flag(args, "no-warn-common")) { ctx.arg.warn_common = false; + } else if (read_flag(args, "warn-once")) { + ctx.arg.warn_once = true; } else if (read_arg(ctx, args, arg, "compress-debug-sections")) { if (arg == "zlib" || arg == "zlib-gabi") ctx.arg.compress_debug_sections = COMPRESS_GABI; diff --git a/elf/input-files.cc b/elf/input-files.cc index 44567e8f40..014ffaadca 100644 --- a/elf/input-files.cc +++ b/elf/input-files.cc @@ -917,7 +917,7 @@ void ObjectFile::claim_unresolved_symbols(Context &ctx) { }; if (ctx.arg.unresolved_symbols == UNRESOLVED_WARN) - Warn(ctx) << "undefined symbol: " << *this << ": " << sym; + report_undef(ctx, *this, sym); // Convert remaining undefined symbols to dynamic symbols. if (ctx.arg.shared) { diff --git a/elf/input-sections.cc b/elf/input-sections.cc index a1457c0bc0..0a955f42e0 100644 --- a/elf/input-sections.cc +++ b/elf/input-sections.cc @@ -200,7 +200,10 @@ void InputSection::write_to(Context &ctx, u8 *buf) { } template -void InputSection::report_undef(Context &ctx, Symbol &sym) { +void report_undef(Context &ctx, InputFile &file, Symbol &sym) { + if (ctx.arg.warn_once && !ctx.warned.insert({(void *)&sym, 1})) + return; + switch (ctx.arg.unresolved_symbols) { case UNRESOLVED_ERROR: Error(ctx) << "undefined symbol: " << file << ": " << sym; @@ -213,9 +216,11 @@ void InputSection::report_undef(Context &ctx, Symbol &sym) { } } -#define INSTANTIATE(E) \ - template struct CieRecord; \ - template class InputSection; +#define INSTANTIATE(E) \ + template struct CieRecord; \ + template class InputSection; \ + template void report_undef(Context &, InputFile &, Symbol &) + INSTANTIATE(X86_64); INSTANTIATE(I386); diff --git a/elf/mold.h b/elf/mold.h index 8de04c3f83..953ccddfe3 100644 --- a/elf/mold.h +++ b/elf/mold.h @@ -326,7 +326,6 @@ class InputSection { void dispatch(Context &ctx, Action table[3][4], i64 i, const ElfRel &rel, Symbol &sym); - void report_undef(Context &ctx, Symbol &sym); void copy_contents(Context &ctx, u8 *buf); void copy_contents_riscv(Context &ctx, u8 *buf); @@ -336,6 +335,9 @@ class InputSection { bool is_relr_reloc(Context &ctx, const ElfRel &rel); }; +template +void report_undef(Context &ctx, InputFile &file, Symbol &sym); + // // output-chunks.cc // @@ -1432,6 +1434,7 @@ struct Context { bool strip_debug = false; bool trace = false; bool warn_common = false; + bool warn_once = false; bool z_copyreloc = true; bool z_defs = false; bool z_delete = true; @@ -1535,6 +1538,9 @@ struct Context { std::atomic_bool has_gottp_rel = false; std::atomic_bool has_textrel = false; + // For --warn-once + tbb::concurrent_hash_map warned; + // Output chunks std::unique_ptr> ehdr; std::unique_ptr> shdr; diff --git a/test/elf/warn-once.sh b/test/elf/warn-once.sh new file mode 100755 index 0000000000..325c4fc35e --- /dev/null +++ b/test/elf/warn-once.sh @@ -0,0 +1,30 @@ +#!/bin/bash +export LANG= +set -e +CC="${CC:-cc}" +CXX="${CXX:-c++}" +testname=$(basename "$0" .sh) +echo -n "Testing $testname ... " +cd "$(dirname "$0")"/../.. +mold="$(pwd)/mold" +t=out/test/elf/$testname +mkdir -p $t + +cat <& $t/log1 +$CC -B. -o $t/exe $t/a.o $t/b.o -Wl,--warn-unresolved-symbols,--warn-once >& $t/log2 + +[ "$(grep 'undefined symbol:.* foo$' $t/log1 | wc -l)" = 2 ] +[ "$(grep 'undefined symbol:.* foo$' $t/log2 | wc -l)" = 1 ] + +echo OK