From 7d17aa83ebeabeea1626fd21d94774993b5692b3 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 10 Apr 2024 15:17:15 +0900 Subject: [PATCH] Add --Bsymbolic-non-weak and --Bsymbolic-non-weak-functions GNU ld doesn't support these options, but LLVM lld do. --- docs/mold.md | 12 ++++++- elf/cmdline.cc | 22 ++++++++----- elf/mold.h | 11 +++++-- elf/passes.cc | 25 +++++++++++--- test/elf/bsymbolic-non-weak-functions.sh | 42 ++++++++++++++++++++++++ test/elf/bsymbolic-non-weak.sh | 42 ++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 15 deletions(-) create mode 100755 test/elf/bsymbolic-non-weak-functions.sh create mode 100755 test/elf/bsymbolic-non-weak.sh diff --git a/docs/mold.md b/docs/mold.md index 9b56de7f96..81d12c123c 100644 --- a/docs/mold.md +++ b/docs/mold.md @@ -350,8 +350,18 @@ but as `-o magic`. This option has the same effect as `--Bsymbolic` but works only for function symbols. Data symbols remain being both imported and exported. +* `--Bsymbolic-non-weak`: + This option has the same effect as `--Bsymbolic` but works only for non-weak + symbols. Weak symbols remain being both imported and exported. + +* `--Bsymbolic-non-weak-functions`: + This option has the same effect as `--Bsymbolic` but works only for non-weak + function symbols. Data symbols and weak function symbols remain being both + imported and exported. + * `--Bno-symbolic`: - Cancel `--Bsymbolic` and `--Bsymbolic-functions`. + Cancel `--Bsymbolic`, `--Bsymbolic-functions`, `--Bsymbolic-non-weak` and + `--Bsymbolic-non-weak-functions`. * `--Map`=_file_: Write map file to _file_. diff --git a/elf/cmdline.cc b/elf/cmdline.cc index c223ee7ea9..632968aaab 100644 --- a/elf/cmdline.cc +++ b/elf/cmdline.cc @@ -56,9 +56,12 @@ inline const char helpmsg[] = R"( Trace references to SYMBOL --Bdynamic, --dy Link against shared libraries (default) --Bstatic, --dn, --static Do not link against shared libraries - --Bsymbolic Bind global symbols locally - --Bsymbolic-functions Bind global functions locally - --Bno-symbolic Cancel --Bsymbolic and --Bsymbolic-functions + --Bsymbolic Bind all symbols locally + --Bsymbolic-functions Bind function symbols locally + --Bsymbolic-non-weak Bind all but weak symbols locally + --Bsymbolic-non-weak-functions + Bind all but weak function symbols locally + --Bno-symbolic Cancel --Bsymbolic options --Map FILE Write map file to a given file --Tbss=ADDR Set address to .bss --Tdata=ADDR Set address to .data @@ -684,12 +687,15 @@ std::vector parse_nonpositional_args(Context &ctx) { } else if (read_flag("no-export-dynamic")) { ctx.arg.export_dynamic = false; } else if (read_flag("Bsymbolic")) { - ctx.arg.Bsymbolic = true; + ctx.arg.Bsymbolic = BSYMBOLIC_ALL; } else if (read_flag("Bsymbolic-functions")) { - ctx.arg.Bsymbolic_functions = true; + ctx.arg.Bsymbolic = BSYMBOLIC_FUNCTIONS; + } else if (read_flag("Bsymbolic-non-weak")) { + ctx.arg.Bsymbolic = BSYMBOLIC_NON_WEAK; + } else if (read_flag("Bsymbolic-non-weak-functions")) { + ctx.arg.Bsymbolic = BSYMBOLIC_NON_WEAK_FUNCTIONS; } else if (read_flag("Bno-symbolic")) { - ctx.arg.Bsymbolic = false; - ctx.arg.Bsymbolic_functions = false; + ctx.arg.Bsymbolic = BSYMBOLIC_NONE; } else if (read_arg("exclude-libs")) { append(ctx.arg.exclude_libs, split_by_comma_or_colon(arg)); } else if (read_flag("q") || read_flag("emit-relocs")) { @@ -1235,7 +1241,7 @@ std::vector parse_nonpositional_args(Context &ctx) { // cannot be done right here. remaining.push_back("--version-script=" + std::string(arg)); } else if (read_arg("dynamic-list")) { - ctx.arg.Bsymbolic = true; + ctx.arg.Bsymbolic = BSYMBOLIC_ALL; append(ctx.dynamic_list_patterns, parse_dynamic_list(ctx, arg)); } else if (read_arg("export-dynamic-symbol")) { ctx.dynamic_list_patterns.push_back({arg, ""}); diff --git a/elf/mold.h b/elf/mold.h index 6ebd87b29f..2a60f7f788 100644 --- a/elf/mold.h +++ b/elf/mold.h @@ -1549,6 +1549,14 @@ typedef enum { UNRESOLVED_IGNORE, } UnresolvedKind; +typedef enum { + BSYMBOLIC_NONE, + BSYMBOLIC_ALL, + BSYMBOLIC_FUNCTIONS, + BSYMBOLIC_NON_WEAK, + BSYMBOLIC_NON_WEAK_FUNCTIONS, +} BsymbolicKind; + typedef enum { SEPARATE_LOADABLE_SEGMENTS, SEPARATE_CODE, @@ -1652,8 +1660,7 @@ struct Context { Symbol *fini = nullptr; Symbol *init = nullptr; UnresolvedKind unresolved_symbols = UNRESOLVED_ERROR; - bool Bsymbolic = false; - bool Bsymbolic_functions = false; + BsymbolicKind Bsymbolic = BSYMBOLIC_NONE; bool allow_multiple_definition = false; bool apply_dynamic_relocs = true; bool color_diagnostics = false; diff --git a/elf/passes.cc b/elf/passes.cc index 515f35b8de..a1ef985c70 100644 --- a/elf/passes.cc +++ b/elf/passes.cc @@ -1899,6 +1899,26 @@ void compute_import_export(Context &ctx) { } }; + auto is_protected = [&](Symbol &sym) { + if (sym.visibility == STV_PROTECTED) + return true; + + switch (ctx.arg.Bsymbolic) { + case BSYMBOLIC_ALL: + return true; + case BSYMBOLIC_NONE: + return false; + case BSYMBOLIC_FUNCTIONS: + return sym.get_type() == STT_FUNC; + case BSYMBOLIC_NON_WEAK: + return !sym.is_weak; + case BSYMBOLIC_NON_WEAK_FUNCTIONS: + return !sym.is_weak && sym.get_type() == STT_FUNC; + default: + unreachable(); + } + }; + // Export symbols that are not hidden or marked as local. // We also want to mark imported symbols as such. tbb::parallel_for_each(ctx.objs, [&](ObjectFile *file) { @@ -1916,10 +1936,7 @@ void compute_import_export(Context &ctx) { // Exported symbols are marked as imported as well by default // for DSOs. - if (ctx.arg.shared && - sym->visibility != STV_PROTECTED && - !ctx.arg.Bsymbolic && - !(ctx.arg.Bsymbolic_functions && sym->get_type() == STT_FUNC)) + if (ctx.arg.shared && !is_protected(*sym)) sym->is_imported = true; } } diff --git a/test/elf/bsymbolic-non-weak-functions.sh b/test/elf/bsymbolic-non-weak-functions.sh new file mode 100755 index 0000000000..36c19299cf --- /dev/null +++ b/test/elf/bsymbolic-non-weak-functions.sh @@ -0,0 +1,42 @@ +#!/bin/bash +. $(dirname $0)/common.inc + +cat < + +int foo = 3; +int bar = 3; +int baz = 3; + +int get_foo1() { return 7; } +int get_bar1() { return 7; } +int get_baz1() { return 7; } + +int get_foo2(); +int get_bar2(); +int get_baz2(); + +int main() { + printf("%d %d %d %d %d %d\n", foo, bar, baz, + get_foo2(), get_bar2(), get_baz2()); +} +EOF + +$CC -B. -o $t/exe $t/c.o $t/b.so +$QEMU $t/exe | grep -q '^3 3 3 3 3 7$' diff --git a/test/elf/bsymbolic-non-weak.sh b/test/elf/bsymbolic-non-weak.sh new file mode 100755 index 0000000000..284a9970eb --- /dev/null +++ b/test/elf/bsymbolic-non-weak.sh @@ -0,0 +1,42 @@ +#!/bin/bash +. $(dirname $0)/common.inc + +cat < + +int foo = 3; +int bar = 3; +int baz = 3; + +int get_foo1() { return 7; } +int get_bar1() { return 7; } +int get_baz1() { return 7; } + +int get_foo2(); +int get_bar2(); +int get_baz2(); + +int main() { + printf("%d %d %d %d %d %d\n", foo, bar, baz, + get_foo2(), get_bar2(), get_baz2()); +} +EOF + +$CC -B. -o $t/exe $t/c.o $t/b.so +$QEMU $t/exe | grep -q '^3 3 3 3 4 7$'