From 03e0cef726571fa0f6435ae0ef9d4146a285b1f8 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sat, 5 Feb 2022 11:57:36 +0900 Subject: [PATCH] [ELF] Add --warn-shared-textrel --- elf/cmdline.cc | 3 +++ elf/input-sections.cc | 12 +++++++++-- elf/mold.h | 1 + elf/passes.cc | 3 +++ test/elf/warn-shared-textrel.sh | 36 +++++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 2 deletions(-) create mode 100755 test/elf/warn-shared-textrel.sh diff --git a/elf/cmdline.cc b/elf/cmdline.cc index 74c17cbb..2f1e5b86 100644 --- a/elf/cmdline.cc +++ b/elf/cmdline.cc @@ -133,6 +133,7 @@ Options: --warn-common Warn about common symbols --no-warn-common --warn-once Only warn once for each undefined symbol + --warn-shared-textrel Warn if the output .so needs text relocations --warn-unresolved-symbols Report unresolved symbols as warnings --error-unresolved-symbols Report unresolved symbols as errors (default) @@ -587,6 +588,8 @@ void parse_nonpositional_args(Context &ctx, ctx.arg.warn_common = false; } else if (read_flag(args, "warn-once")) { ctx.arg.warn_once = true; + } else if (read_flag(args, "warn-shared-textrel")) { + ctx.arg.warn_shared_textrel = 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-sections.cc b/elf/input-sections.cc index 0a955f42..14c357b4 100644 --- a/elf/input-sections.cc +++ b/elf/input-sections.cc @@ -121,6 +121,12 @@ void InputSection::dispatch(Context &ctx, Action table[3][4], i64 i, << sym << "' can not be used; recompile with -fPIC"; }; + auto warn_textrel = [&]() { + if (ctx.arg.shared && ctx.arg.warn_shared_textrel) + Warn(ctx) << *this << ": relocation against symbol `" << sym + << "' in read-only section"; + }; + switch (action) { case NONE: return; @@ -148,10 +154,11 @@ void InputSection::dispatch(Context &ctx, Action table[3][4], i64 i, return; case DYNREL: if (!is_writable) { - if (!is_code || ctx.arg.z_text) { + if (ctx.arg.z_text) { error(); return; } + warn_textrel(); ctx.has_textrel = true; } @@ -161,10 +168,11 @@ void InputSection::dispatch(Context &ctx, Action table[3][4], i64 i, return; case BASEREL: if (!is_writable) { - if (!is_code || ctx.arg.z_text) { + if (ctx.arg.z_text) { error(); return; } + warn_textrel(); ctx.has_textrel = true; } diff --git a/elf/mold.h b/elf/mold.h index 953ccddf..cf7b6562 100644 --- a/elf/mold.h +++ b/elf/mold.h @@ -1435,6 +1435,7 @@ struct Context { bool trace = false; bool warn_common = false; bool warn_once = false; + bool warn_shared_textrel = false; bool z_copyreloc = true; bool z_defs = false; bool z_delete = true; diff --git a/elf/passes.cc b/elf/passes.cc index dad03415..8278d84e 100644 --- a/elf/passes.cc +++ b/elf/passes.cc @@ -678,6 +678,9 @@ void scan_rels(Context &ctx) { if (ctx.needs_tlsld) ctx.got->add_tlsld(ctx); + + if (ctx.arg.shared && ctx.arg.warn_shared_textrel && ctx.has_textrel) + Warn(ctx) << "--warn-shared-textrel: creating a DT_TEXTREL in a shared object"; } template diff --git a/test/elf/warn-shared-textrel.sh b/test/elf/warn-shared-textrel.sh new file mode 100755 index 00000000..64cee4ca --- /dev/null +++ b/test/elf/warn-shared-textrel.sh @@ -0,0 +1,36 @@ +#!/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 + +# Skip if libc is musl +echo 'int main() {}' | $CC -o $t/exe -xc - +ldd $t/exe | grep -q ld-musl && { echo OK; exit; } + +# Skip if target is not x86-64 +[ "$(uname -m)" = x86_64 ] || { echo skipped; exit; } + +cat <<'EOF' | $CC -c -o $t/a.o -x assembler - +.globl fn +fn: + movabs main, %rax + ret +EOF + +cat <& $t/log +grep -q 'relocation against symbol `main'\'' in read-only section' $t/log +grep -q 'creating a DT_TEXTREL in a shared object' $t/log + +echo OK